/* armv8-curve25519
 *
 * Copyright (C) 2006-2025 wolfSSL Inc.
 *
 * This file is part of wolfSSL.
 *
 * wolfSSL is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * wolfSSL is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
 */

#include <wolfssl/wolfcrypt/libwolfssl_sources_asm.h>
#include <wolfssl/wolfcrypt/error-crypt.h>

/* Generated using (from wolfssl):
 *   cd ../scripts
 *   ruby ./x25519/x25519.rb arm64 \
 *       ../wolfssl/wolfcrypt/src/port/arm/armv8-curve25519.c
 */
#ifdef WOLFSSL_ARMASM
#ifdef __aarch64__
#ifdef WOLFSSL_ARMASM_INLINE
#include <wolfssl/wolfcrypt/fe_operations.h>
#define CURVED25519_ASM
#include <wolfssl/wolfcrypt/ge_operations.h>

#if defined(HAVE_CURVE25519) || defined(HAVE_ED25519)
#if !defined(CURVE25519_SMALL) || !defined(ED25519_SMALL)
#include <wolfssl/wolfcrypt/fe_operations.h>

void fe_init()
{
    __asm__ __volatile__ (
        "\n\t"
        :
        :
        : "memory", "cc"
    );
}

#ifdef HAVE_ED25519
void fe_frombytes(fe out, const unsigned char* in)
{
    __asm__ __volatile__ (
        "ldp	x2, x3, [%x[in]]\n\t"
        "ldp	x4, x5, [%x[in], #16]\n\t"
        "and	x5, x5, #0x7fffffffffffffff\n\t"
        "stp	x2, x3, [%x[out]]\n\t"
        "stp	x4, x5, [%x[out], #16]\n\t"
        : [out] "+r" (out)
        : [in] "r" (in)
        : "memory", "cc", "x2", "x3", "x4", "x5", "x6"
    );
}

void fe_tobytes(unsigned char* out, const fe n)
{
    __asm__ __volatile__ (
        "mov	x7, #19\n\t"
        "ldp	x2, x3, [%x[n]]\n\t"
        "ldp	x4, x5, [%x[n], #16]\n\t"
        "adds	x6, x2, x7\n\t"
        "adcs	x6, x3, xzr\n\t"
        "adcs	x6, x4, xzr\n\t"
        "adc	x6, x5, xzr\n\t"
        "and	x6, x7, x6, asr 63\n\t"
        "adds	x2, x2, x6\n\t"
        "adcs	x3, x3, xzr\n\t"
        "adcs	x4, x4, xzr\n\t"
        "adc	x5, x5, xzr\n\t"
        "and	x5, x5, #0x7fffffffffffffff\n\t"
        "stp	x2, x3, [%x[out]]\n\t"
        "stp	x4, x5, [%x[out], #16]\n\t"
        : [out] "+r" (out)
        : [n] "r" (n)
        : "memory", "cc", "x2", "x3", "x4", "x5", "x6", "x7"
    );
}

void fe_1(fe n)
{
    __asm__ __volatile__ (
        /* Set one */
        "mov	x1, #1\n\t"
        "stp	x1, xzr, [%x[n]]\n\t"
        "stp	xzr, xzr, [%x[n], #16]\n\t"
        : [n] "+r" (n)
        :
        : "memory", "cc", "x1"
    );
}

void fe_0(fe n)
{
    __asm__ __volatile__ (
        /* Set zero */
        "stp	xzr, xzr, [%x[n]]\n\t"
        "stp	xzr, xzr, [%x[n], #16]\n\t"
        : [n] "+r" (n)
        :
        : "memory", "cc"
    );
}

void fe_copy(fe r, const fe a)
{
    __asm__ __volatile__ (
        /* Copy */
        "ldp	x2, x3, [%x[a]]\n\t"
        "ldp	x4, x5, [%x[a], #16]\n\t"
        "stp	x2, x3, [%x[r]]\n\t"
        "stp	x4, x5, [%x[r], #16]\n\t"
        : [r] "+r" (r)
        : [a] "r" (a)
        : "memory", "cc", "x2", "x3", "x4", "x5"
    );
}

void fe_sub(fe r, const fe a, const fe b)
{
    __asm__ __volatile__ (
        /* Sub */
        "ldp	x3, x4, [%x[a]]\n\t"
        "ldp	x5, x6, [%x[a], #16]\n\t"
        "ldp	x7, x8, [%x[b]]\n\t"
        "ldp	x9, x10, [%x[b], #16]\n\t"
        "subs	x3, x3, x7\n\t"
        "sbcs	x4, x4, x8\n\t"
        "sbcs	x5, x5, x9\n\t"
        "sbcs	x6, x6, x10\n\t"
        "csetm	x11, cc\n\t"
        "mov	x12, #-19\n\t"
        /*   Mask the modulus */
        "extr	x11, x11, x6, #63\n\t"
        "mul	x12, x11, x12\n\t"
        /*   Add modulus (if underflow) */
        "subs	x3, x3, x12\n\t"
        "sbcs	x4, x4, xzr\n\t"
        "and	x6, x6, #0x7fffffffffffffff\n\t"
        "sbcs	x5, x5, xzr\n\t"
        "sbc	x6, x6, xzr\n\t"
        "stp	x3, x4, [%x[r]]\n\t"
        "stp	x5, x6, [%x[r], #16]\n\t"
        : [r] "+r" (r)
        : [a] "r" (a), [b] "r" (b)
        : "memory", "cc", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10",
            "x11", "x12", "x13"
    );
}

void fe_add(fe r, const fe a, const fe b)
{
    __asm__ __volatile__ (
        /* Add */
        "ldp	x3, x4, [%x[a]]\n\t"
        "ldp	x5, x6, [%x[a], #16]\n\t"
        "ldp	x7, x8, [%x[b]]\n\t"
        "ldp	x9, x10, [%x[b], #16]\n\t"
        "adds	x3, x3, x7\n\t"
        "adcs	x4, x4, x8\n\t"
        "adcs	x5, x5, x9\n\t"
        "adcs	x6, x6, x10\n\t"
        "cset	x11, cs\n\t"
        "mov	x12, #19\n\t"
        /*   Mask the modulus */
        "extr	x11, x11, x6, #63\n\t"
        "mul	x12, x11, x12\n\t"
        /*   Sub modulus (if overflow) */
        "adds	x3, x3, x12\n\t"
        "adcs	x4, x4, xzr\n\t"
        "and	x6, x6, #0x7fffffffffffffff\n\t"
        "adcs	x5, x5, xzr\n\t"
        "adc	x6, x6, xzr\n\t"
        "stp	x3, x4, [%x[r]]\n\t"
        "stp	x5, x6, [%x[r], #16]\n\t"
        : [r] "+r" (r)
        : [a] "r" (a), [b] "r" (b)
        : "memory", "cc", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10",
            "x11", "x12", "x13"
    );
}

void fe_neg(fe r, const fe a)
{
    __asm__ __volatile__ (
        "ldp	x2, x3, [%x[a]]\n\t"
        "ldp	x4, x5, [%x[a], #16]\n\t"
        "mov	x6, #-19\n\t"
        "mov	x7, #-1\n\t"
        "mov	x8, #-1\n\t"
        "mov	x9, #0x7fffffffffffffff\n\t"
        "subs	x6, x6, x2\n\t"
        "sbcs	x7, x7, x3\n\t"
        "sbcs	x8, x8, x4\n\t"
        "sbc	x9, x9, x5\n\t"
        "stp	x6, x7, [%x[r]]\n\t"
        "stp	x8, x9, [%x[r], #16]\n\t"
        : [r] "+r" (r)
        : [a] "r" (a)
        : "memory", "cc", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9"
    );
}

int fe_isnonzero(const fe a)
{
    __asm__ __volatile__ (
        "mov	x6, #19\n\t"
        "ldp	x1, x2, [%x[a]]\n\t"
        "ldp	x3, x4, [%x[a], #16]\n\t"
        "adds	x5, x1, x6\n\t"
        "adcs	x5, x2, xzr\n\t"
        "adcs	x5, x3, xzr\n\t"
        "adc	x5, x4, xzr\n\t"
        "and	x5, x6, x5, asr 63\n\t"
        "adds	x1, x1, x5\n\t"
        "adcs	x2, x2, xzr\n\t"
        "adcs	x3, x3, xzr\n\t"
        "adc	x4, x4, xzr\n\t"
        "and	x4, x4, #0x7fffffffffffffff\n\t"
        "orr	%x[a], x1, x2\n\t"
        "orr	x3, x3, x4\n\t"
        "orr	%x[a], %x[a], x3\n\t"
        :
        : [a] "r" (a)
        : "memory", "cc", "x1", "x2", "x3", "x4", "x5", "x6"
    );
    return (word32)(size_t)a;
}

int fe_isnegative(const fe a)
{
    __asm__ __volatile__ (
        "mov	x6, #19\n\t"
        "ldp	x1, x2, [%x[a]]\n\t"
        "ldp	x3, x4, [%x[a], #16]\n\t"
        "adds	x5, x1, x6\n\t"
        "adcs	x5, x2, xzr\n\t"
        "adcs	x5, x3, xzr\n\t"
        "adc	x5, x4, xzr\n\t"
        "and	%x[a], x1, #1\n\t"
        "eor	%x[a], %x[a], x5, lsr 63\n\t"
        :
        : [a] "r" (a)
        : "memory", "cc", "x1", "x2", "x3", "x4", "x5", "x6"
    );
    return (word32)(size_t)a;
}

void fe_cmov_table(fe* r, fe* base, signed char b)
{
    __asm__ __volatile__ (
        "stp	x29, x30, [sp, #-32]!\n\t"
        "add	x29, sp, #0\n\t"
        "str	%x[r], [x29, #16]\n\t"
        "sxtb	%x[b], %w[b]\n\t"
        "sbfx	x3, %x[b], #7, #1\n\t"
        "eor	%x[r], %x[b], x3\n\t"
        "sub	%x[r], %x[r], x3\n\t"
        "mov	x4, #1\n\t"
        "mov	x5, xzr\n\t"
        "mov	x6, xzr\n\t"
        "mov	x7, xzr\n\t"
        "mov	x8, #1\n\t"
        "mov	x9, xzr\n\t"
        "mov	x10, xzr\n\t"
        "mov	x11, xzr\n\t"
        "mov	x12, xzr\n\t"
        "mov	x13, xzr\n\t"
        "mov	x14, xzr\n\t"
        "mov	x15, xzr\n\t"
        "cmp	%x[r], #1\n\t"
        "ldp	x16, x17, [%x[base]]\n\t"
        "ldp	x19, x20, [%x[base], #16]\n\t"
        "ldp	x21, x22, [%x[base], #32]\n\t"
        "ldp	x23, x24, [%x[base], #48]\n\t"
        "ldp	x25, x26, [%x[base], #64]\n\t"
        "ldp	x27, x28, [%x[base], #80]\n\t"
        "csel	x4, x16, x4, eq\n\t"
        "csel	x5, x17, x5, eq\n\t"
        "csel	x6, x19, x6, eq\n\t"
        "csel	x7, x20, x7, eq\n\t"
        "csel	x8, x21, x8, eq\n\t"
        "csel	x9, x22, x9, eq\n\t"
        "csel	x10, x23, x10, eq\n\t"
        "csel	x11, x24, x11, eq\n\t"
        "csel	x12, x25, x12, eq\n\t"
        "csel	x13, x26, x13, eq\n\t"
        "csel	x14, x27, x14, eq\n\t"
        "csel	x15, x28, x15, eq\n\t"
        "cmp	%x[r], #2\n\t"
        "ldp	x16, x17, [%x[base], #96]\n\t"
        "ldp	x19, x20, [%x[base], #112]\n\t"
        "ldp	x21, x22, [%x[base], #128]\n\t"
        "ldp	x23, x24, [%x[base], #144]\n\t"
        "ldp	x25, x26, [%x[base], #160]\n\t"
        "ldp	x27, x28, [%x[base], #176]\n\t"
        "csel	x4, x16, x4, eq\n\t"
        "csel	x5, x17, x5, eq\n\t"
        "csel	x6, x19, x6, eq\n\t"
        "csel	x7, x20, x7, eq\n\t"
        "csel	x8, x21, x8, eq\n\t"
        "csel	x9, x22, x9, eq\n\t"
        "csel	x10, x23, x10, eq\n\t"
        "csel	x11, x24, x11, eq\n\t"
        "csel	x12, x25, x12, eq\n\t"
        "csel	x13, x26, x13, eq\n\t"
        "csel	x14, x27, x14, eq\n\t"
        "csel	x15, x28, x15, eq\n\t"
        "cmp	%x[r], #3\n\t"
        "ldp	x16, x17, [%x[base], #192]\n\t"
        "ldp	x19, x20, [%x[base], #208]\n\t"
        "ldp	x21, x22, [%x[base], #224]\n\t"
        "ldp	x23, x24, [%x[base], #240]\n\t"
        "ldp	x25, x26, [%x[base], #256]\n\t"
        "ldp	x27, x28, [%x[base], #272]\n\t"
        "csel	x4, x16, x4, eq\n\t"
        "csel	x5, x17, x5, eq\n\t"
        "csel	x6, x19, x6, eq\n\t"
        "csel	x7, x20, x7, eq\n\t"
        "csel	x8, x21, x8, eq\n\t"
        "csel	x9, x22, x9, eq\n\t"
        "csel	x10, x23, x10, eq\n\t"
        "csel	x11, x24, x11, eq\n\t"
        "csel	x12, x25, x12, eq\n\t"
        "csel	x13, x26, x13, eq\n\t"
        "csel	x14, x27, x14, eq\n\t"
        "csel	x15, x28, x15, eq\n\t"
        "cmp	%x[r], #4\n\t"
        "ldp	x16, x17, [%x[base], #288]\n\t"
        "ldp	x19, x20, [%x[base], #304]\n\t"
        "ldp	x21, x22, [%x[base], #320]\n\t"
        "ldp	x23, x24, [%x[base], #336]\n\t"
        "ldp	x25, x26, [%x[base], #352]\n\t"
        "ldp	x27, x28, [%x[base], #368]\n\t"
        "csel	x4, x16, x4, eq\n\t"
        "csel	x5, x17, x5, eq\n\t"
        "csel	x6, x19, x6, eq\n\t"
        "csel	x7, x20, x7, eq\n\t"
        "csel	x8, x21, x8, eq\n\t"
        "csel	x9, x22, x9, eq\n\t"
        "csel	x10, x23, x10, eq\n\t"
        "csel	x11, x24, x11, eq\n\t"
        "csel	x12, x25, x12, eq\n\t"
        "csel	x13, x26, x13, eq\n\t"
        "csel	x14, x27, x14, eq\n\t"
        "csel	x15, x28, x15, eq\n\t"
        "add	%x[base], %x[base], #0x180\n\t"
        "cmp	%x[r], #5\n\t"
        "ldp	x16, x17, [%x[base]]\n\t"
        "ldp	x19, x20, [%x[base], #16]\n\t"
        "ldp	x21, x22, [%x[base], #32]\n\t"
        "ldp	x23, x24, [%x[base], #48]\n\t"
        "ldp	x25, x26, [%x[base], #64]\n\t"
        "ldp	x27, x28, [%x[base], #80]\n\t"
        "csel	x4, x16, x4, eq\n\t"
        "csel	x5, x17, x5, eq\n\t"
        "csel	x6, x19, x6, eq\n\t"
        "csel	x7, x20, x7, eq\n\t"
        "csel	x8, x21, x8, eq\n\t"
        "csel	x9, x22, x9, eq\n\t"
        "csel	x10, x23, x10, eq\n\t"
        "csel	x11, x24, x11, eq\n\t"
        "csel	x12, x25, x12, eq\n\t"
        "csel	x13, x26, x13, eq\n\t"
        "csel	x14, x27, x14, eq\n\t"
        "csel	x15, x28, x15, eq\n\t"
        "cmp	%x[r], #6\n\t"
        "ldp	x16, x17, [%x[base], #96]\n\t"
        "ldp	x19, x20, [%x[base], #112]\n\t"
        "ldp	x21, x22, [%x[base], #128]\n\t"
        "ldp	x23, x24, [%x[base], #144]\n\t"
        "ldp	x25, x26, [%x[base], #160]\n\t"
        "ldp	x27, x28, [%x[base], #176]\n\t"
        "csel	x4, x16, x4, eq\n\t"
        "csel	x5, x17, x5, eq\n\t"
        "csel	x6, x19, x6, eq\n\t"
        "csel	x7, x20, x7, eq\n\t"
        "csel	x8, x21, x8, eq\n\t"
        "csel	x9, x22, x9, eq\n\t"
        "csel	x10, x23, x10, eq\n\t"
        "csel	x11, x24, x11, eq\n\t"
        "csel	x12, x25, x12, eq\n\t"
        "csel	x13, x26, x13, eq\n\t"
        "csel	x14, x27, x14, eq\n\t"
        "csel	x15, x28, x15, eq\n\t"
        "cmp	%x[r], #7\n\t"
        "ldp	x16, x17, [%x[base], #192]\n\t"
        "ldp	x19, x20, [%x[base], #208]\n\t"
        "ldp	x21, x22, [%x[base], #224]\n\t"
        "ldp	x23, x24, [%x[base], #240]\n\t"
        "ldp	x25, x26, [%x[base], #256]\n\t"
        "ldp	x27, x28, [%x[base], #272]\n\t"
        "csel	x4, x16, x4, eq\n\t"
        "csel	x5, x17, x5, eq\n\t"
        "csel	x6, x19, x6, eq\n\t"
        "csel	x7, x20, x7, eq\n\t"
        "csel	x8, x21, x8, eq\n\t"
        "csel	x9, x22, x9, eq\n\t"
        "csel	x10, x23, x10, eq\n\t"
        "csel	x11, x24, x11, eq\n\t"
        "csel	x12, x25, x12, eq\n\t"
        "csel	x13, x26, x13, eq\n\t"
        "csel	x14, x27, x14, eq\n\t"
        "csel	x15, x28, x15, eq\n\t"
        "cmp	%x[r], #8\n\t"
        "ldp	x16, x17, [%x[base], #288]\n\t"
        "ldp	x19, x20, [%x[base], #304]\n\t"
        "ldp	x21, x22, [%x[base], #320]\n\t"
        "ldp	x23, x24, [%x[base], #336]\n\t"
        "ldp	x25, x26, [%x[base], #352]\n\t"
        "ldp	x27, x28, [%x[base], #368]\n\t"
        "csel	x4, x16, x4, eq\n\t"
        "csel	x5, x17, x5, eq\n\t"
        "csel	x6, x19, x6, eq\n\t"
        "csel	x7, x20, x7, eq\n\t"
        "csel	x8, x21, x8, eq\n\t"
        "csel	x9, x22, x9, eq\n\t"
        "csel	x10, x23, x10, eq\n\t"
        "csel	x11, x24, x11, eq\n\t"
        "csel	x12, x25, x12, eq\n\t"
        "csel	x13, x26, x13, eq\n\t"
        "csel	x14, x27, x14, eq\n\t"
        "csel	x15, x28, x15, eq\n\t"
        "mov	x16, #-19\n\t"
        "mov	x17, #-1\n\t"
        "mov	x19, #-1\n\t"
        "mov	x20, #0x7fffffffffffffff\n\t"
        "subs	x16, x16, x12\n\t"
        "sbcs	x17, x17, x13\n\t"
        "sbcs	x19, x19, x14\n\t"
        "sbc	x20, x20, x15\n\t"
        "cmp	%x[b], #0\n\t"
        "mov	x3, x4\n\t"
        "csel	x4, x8, x4, lt\n\t"
        "csel	x8, x3, x8, lt\n\t"
        "mov	x3, x5\n\t"
        "csel	x5, x9, x5, lt\n\t"
        "csel	x9, x3, x9, lt\n\t"
        "mov	x3, x6\n\t"
        "csel	x6, x10, x6, lt\n\t"
        "csel	x10, x3, x10, lt\n\t"
        "mov	x3, x7\n\t"
        "csel	x7, x11, x7, lt\n\t"
        "csel	x11, x3, x11, lt\n\t"
        "csel	x12, x16, x12, lt\n\t"
        "csel	x13, x17, x13, lt\n\t"
        "csel	x14, x19, x14, lt\n\t"
        "csel	x15, x20, x15, lt\n\t"
        "ldr	%x[r], [x29, #16]\n\t"
        "stp	x4, x5, [%x[r]]\n\t"
        "stp	x6, x7, [%x[r], #16]\n\t"
        "stp	x8, x9, [%x[r], #32]\n\t"
        "stp	x10, x11, [%x[r], #48]\n\t"
        "stp	x12, x13, [%x[r], #64]\n\t"
        "stp	x14, x15, [%x[r], #80]\n\t"
        "ldp	x29, x30, [sp], #32\n\t"
        : [r] "+r" (r), [base] "+r" (base), [b] "+r" (b)
        :
        : "memory", "cc", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10",
            "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20",
            "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28"
    );
}

#endif /* HAVE_ED25519 */
void fe_mul(fe r, const fe a, const fe b)
{
    __asm__ __volatile__ (
        /* Multiply */
        "ldp	x14, x15, [%x[a]]\n\t"
        "ldp	x16, x17, [%x[a], #16]\n\t"
        "ldp	x19, x20, [%x[b]]\n\t"
        "ldp	x21, x22, [%x[b], #16]\n\t"
        /* A[0] * B[0] */
        "umulh	x7, x14, x19\n\t"
        "mul	x6, x14, x19\n\t"
        /* A[2] * B[0] */
        "umulh	x9, x16, x19\n\t"
        "mul	x8, x16, x19\n\t"
        /* A[1] * B[0] */
        "mul	x3, x15, x19\n\t"
        "adds	x7, x7, x3\n\t"
        "umulh	x4, x15, x19\n\t"
        "adcs	x8, x8, x4\n\t"
        /* A[1] * B[3] */
        "umulh	x11, x15, x22\n\t"
        "adc	x9, x9, xzr\n\t"
        "mul	x10, x15, x22\n\t"
        /* A[0] * B[1] */
        "mul	x3, x14, x20\n\t"
        "adds	x7, x7, x3\n\t"
        "umulh	x4, x14, x20\n\t"
        "adcs	x8, x8, x4\n\t"
        /* A[2] * B[1] */
        "mul	x3, x16, x20\n\t"
        "adcs	x9, x9, x3\n\t"
        "umulh	x4, x16, x20\n\t"
        "adcs	x10, x10, x4\n\t"
        "adc	x11, x11, xzr\n\t"
        /* A[1] * B[2] */
        "mul	x3, x15, x21\n\t"
        "adds	x9, x9, x3\n\t"
        "umulh	x4, x15, x21\n\t"
        "adcs	x10, x10, x4\n\t"
        "adcs	x11, x11, xzr\n\t"
        "adc	x12, xzr, xzr\n\t"
        /* A[0] * B[2] */
        "mul	x3, x14, x21\n\t"
        "adds	x8, x8, x3\n\t"
        "umulh	x4, x14, x21\n\t"
        "adcs	x9, x9, x4\n\t"
        "adcs	x10, x10, xzr\n\t"
        "adcs	x11, x11, xzr\n\t"
        "adc	x12, x12, xzr\n\t"
        /* A[1] * B[1] */
        "mul	x3, x15, x20\n\t"
        "adds	x8, x8, x3\n\t"
        "umulh	x4, x15, x20\n\t"
        "adcs	x9, x9, x4\n\t"
        /* A[3] * B[1] */
        "mul	x3, x17, x20\n\t"
        "adcs	x10, x10, x3\n\t"
        "umulh	x4, x17, x20\n\t"
        "adcs	x11, x11, x4\n\t"
        "adc	x12, x12, xzr\n\t"
        /* A[2] * B[2] */
        "mul	x3, x16, x21\n\t"
        "adds	x10, x10, x3\n\t"
        "umulh	x4, x16, x21\n\t"
        "adcs	x11, x11, x4\n\t"
        /* A[3] * B[3] */
        "mul	x3, x17, x22\n\t"
        "adcs	x12, x12, x3\n\t"
        "umulh	x13, x17, x22\n\t"
        "adc	x13, x13, xzr\n\t"
        /* A[0] * B[3] */
        "mul	x3, x14, x22\n\t"
        "adds	x9, x9, x3\n\t"
        "umulh	x4, x14, x22\n\t"
        "adcs	x10, x10, x4\n\t"
        /* A[2] * B[3] */
        "mul	x3, x16, x22\n\t"
        "adcs	x11, x11, x3\n\t"
        "umulh	x4, x16, x22\n\t"
        "adcs	x12, x12, x4\n\t"
        "adc	x13, x13, xzr\n\t"
        /* A[3] * B[0] */
        "mul	x3, x17, x19\n\t"
        "adds	x9, x9, x3\n\t"
        "umulh	x4, x17, x19\n\t"
        "adcs	x10, x10, x4\n\t"
        /* A[3] * B[2] */
        "mul	x3, x17, x21\n\t"
        "adcs	x11, x11, x3\n\t"
        "umulh	x4, x17, x21\n\t"
        "adcs	x12, x12, x4\n\t"
        "adc	x13, x13, xzr\n\t"
        /* Reduce */
        "mov	x3, #38\n\t"
        "mul	x4, x3, x13\n\t"
        "adds	x9, x9, x4\n\t"
        "umulh	x5, x3, x13\n\t"
        "adc	x5, x5, xzr\n\t"
        "mov	x3, #19\n\t"
        "extr	x5, x5, x9, #63\n\t"
        "mul	x5, x5, x3\n\t"
        "and	x9, x9, #0x7fffffffffffffff\n\t"
        "mov	x3, #38\n\t"
        "mul	x4, x3, x10\n\t"
        "adds	x6, x6, x4\n\t"
        "umulh	x10, x3, x10\n\t"
        "mul	x4, x3, x11\n\t"
        "adcs	x7, x7, x4\n\t"
        "umulh	x11, x3, x11\n\t"
        "mul	x4, x3, x12\n\t"
        "adcs	x8, x8, x4\n\t"
        "umulh	x12, x3, x12\n\t"
        "adc	x9, x9, xzr\n\t"
        /*  Add high product results in */
        "adds	x6, x6, x5\n\t"
        "adcs	x7, x7, x10\n\t"
        "adcs	x8, x8, x11\n\t"
        "adc	x9, x9, x12\n\t"
        /* Reduce if top bit set */
        "mov	x3, #19\n\t"
        "and	x4, x3, x9, asr 63\n\t"
        "adds	x6, x6, x4\n\t"
        "adcs	x7, x7, xzr\n\t"
        "and	x9, x9, #0x7fffffffffffffff\n\t"
        "adcs	x8, x8, xzr\n\t"
        "adc	x9, x9, xzr\n\t"
        /* Store */
        "stp	x6, x7, [%x[r]]\n\t"
        "stp	x8, x9, [%x[r], #16]\n\t"
        : [r] "+r" (r)
        : [a] "r" (a), [b] "r" (b)
        : "memory", "cc", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10",
            "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20",
            "x21", "x22"
    );
}

void fe_sq(fe r, const fe a)
{
    __asm__ __volatile__ (
        /* Square */
        "ldp	x13, x14, [%x[a]]\n\t"
        "ldp	x15, x16, [%x[a], #16]\n\t"
        /*  A[0] * A[1] */
        "umulh	x7, x13, x14\n\t"
        "mul	x6, x13, x14\n\t"
        /*  A[0] * A[3] */
        "umulh	x9, x13, x16\n\t"
        "mul	x8, x13, x16\n\t"
        /*  A[0] * A[2] */
        "mul	x2, x13, x15\n\t"
        "adds	x7, x7, x2\n\t"
        "umulh	x3, x13, x15\n\t"
        "adcs	x8, x8, x3\n\t"
        /*  A[1] * A[3] */
        "mul	x2, x14, x16\n\t"
        "adcs	x9, x9, x2\n\t"
        "umulh	x10, x14, x16\n\t"
        "adc	x10, x10, xzr\n\t"
        /*  A[1] * A[2] */
        "mul	x2, x14, x15\n\t"
        "adds	x8, x8, x2\n\t"
        "umulh	x3, x14, x15\n\t"
        "adcs	x9, x9, x3\n\t"
        /*  A[2] * A[3] */
        "mul	x2, x15, x16\n\t"
        "adcs	x10, x10, x2\n\t"
        "umulh	x11, x15, x16\n\t"
        "adc	x11, x11, xzr\n\t"
        /* Double */
        "adds	x6, x6, x6\n\t"
        "adcs	x7, x7, x7\n\t"
        "adcs	x8, x8, x8\n\t"
        "adcs	x9, x9, x9\n\t"
        "adcs	x10, x10, x10\n\t"
        "adcs	x11, x11, x11\n\t"
        "adc	x12, xzr, xzr\n\t"
        /*  A[0] * A[0] */
        "umulh	x3, x13, x13\n\t"
        "mul	x5, x13, x13\n\t"
        /*  A[1] * A[1] */
        "mul	x2, x14, x14\n\t"
        "adds	x6, x6, x3\n\t"
        "umulh	x3, x14, x14\n\t"
        "adcs	x7, x7, x2\n\t"
        /*  A[2] * A[2] */
        "mul	x2, x15, x15\n\t"
        "adcs	x8, x8, x3\n\t"
        "umulh	x3, x15, x15\n\t"
        "adcs	x9, x9, x2\n\t"
        /*  A[3] * A[3] */
        "mul	x2, x16, x16\n\t"
        "adcs	x10, x10, x3\n\t"
        "umulh	x3, x16, x16\n\t"
        "adcs	x11, x11, x2\n\t"
        "adc	x12, x12, x3\n\t"
        /* Reduce */
        "mov	x2, #38\n\t"
        "mul	x3, x2, x12\n\t"
        "adds	x8, x8, x3\n\t"
        "umulh	x4, x2, x12\n\t"
        "adc	x4, x4, xzr\n\t"
        "mov	x2, #19\n\t"
        "extr	x4, x4, x8, #63\n\t"
        "mul	x4, x4, x2\n\t"
        "and	x8, x8, #0x7fffffffffffffff\n\t"
        "mov	x2, #38\n\t"
        "mul	x3, x2, x9\n\t"
        "adds	x5, x5, x3\n\t"
        "umulh	x9, x2, x9\n\t"
        "mul	x3, x2, x10\n\t"
        "adcs	x6, x6, x3\n\t"
        "umulh	x10, x2, x10\n\t"
        "mul	x3, x2, x11\n\t"
        "adcs	x7, x7, x3\n\t"
        "umulh	x11, x2, x11\n\t"
        "adc	x8, x8, xzr\n\t"
        /*  Add high product results in */
        "adds	x5, x5, x4\n\t"
        "adcs	x6, x6, x9\n\t"
        "adcs	x7, x7, x10\n\t"
        "adc	x8, x8, x11\n\t"
        /* Reduce if top bit set */
        "mov	x2, #19\n\t"
        "and	x3, x2, x8, asr 63\n\t"
        "adds	x5, x5, x3\n\t"
        "adcs	x6, x6, xzr\n\t"
        "and	x8, x8, #0x7fffffffffffffff\n\t"
        "adcs	x7, x7, xzr\n\t"
        "adc	x8, x8, xzr\n\t"
        /* Store */
        "stp	x5, x6, [%x[r]]\n\t"
        "stp	x7, x8, [%x[r], #16]\n\t"
        : [r] "+r" (r)
        : [a] "r" (a)
        : "memory", "cc", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10",
            "x11", "x12", "x13", "x14", "x15", "x16"
    );
}

void fe_invert(fe r, const fe a)
{
    __asm__ __volatile__ (
        "stp	x29, x30, [sp, #-160]!\n\t"
        "add	x29, sp, #0\n\t"
        /* Invert */
        "str	%x[r], [x29, #144]\n\t"
        "str	%x[a], [x29, #152]\n\t"
        "add	x0, x29, #16\n\t"
#ifndef NDEBUG
        "ldr	x1, [x29, #152]\n\t"
#endif /* !NDEBUG */
#ifndef __APPLE__
        "bl	fe_sq\n\t"
#else
        "bl	_fe_sq\n\t"
#endif /* __APPLE__ */
        "add	x0, x29, #48\n\t"
        "add	x1, x29, #16\n\t"
#ifndef __APPLE__
        "bl	fe_sq\n\t"
#else
        "bl	_fe_sq\n\t"
#endif /* __APPLE__ */
#ifndef NDEBUG
        "add	x0, x29, #48\n\t"
#endif /* !NDEBUG */
        "add	x1, x29, #48\n\t"
#ifndef __APPLE__
        "bl	fe_sq\n\t"
#else
        "bl	_fe_sq\n\t"
#endif /* __APPLE__ */
#ifndef NDEBUG
        "add	x0, x29, #48\n\t"
#endif /* !NDEBUG */
        "ldr	x1, [x29, #152]\n\t"
        "add	x2, x29, #48\n\t"
#ifndef __APPLE__
        "bl	fe_mul\n\t"
#else
        "bl	_fe_mul\n\t"
#endif /* __APPLE__ */
        "add	x0, x29, #16\n\t"
        "add	x1, x29, #16\n\t"
        "add	x2, x29, #48\n\t"
#ifndef __APPLE__
        "bl	fe_mul\n\t"
#else
        "bl	_fe_mul\n\t"
#endif /* __APPLE__ */
        "add	x0, x29, #0x50\n\t"
#ifndef NDEBUG
        "add	x1, x29, #16\n\t"
#endif /* !NDEBUG */
#ifndef __APPLE__
        "bl	fe_sq\n\t"
#else
        "bl	_fe_sq\n\t"
#endif /* __APPLE__ */
        "add	x0, x29, #48\n\t"
        "add	x1, x29, #48\n\t"
        "add	x2, x29, #0x50\n\t"
#ifndef __APPLE__
        "bl	fe_mul\n\t"
#else
        "bl	_fe_mul\n\t"
#endif /* __APPLE__ */
        /* Loop: 5 times */
        "mov	x20, #5\n\t"
        "ldp	x6, x7, [x29, #48]\n\t"
        "ldp	x8, x9, [x29, #64]\n\t"
        "\n"
    "L_fe_invert1_%=: \n\t"
        /* Square */
        /*  A[0] * A[1] */
        "umulh	x12, x6, x7\n\t"
        "mul	x11, x6, x7\n\t"
        /*  A[0] * A[3] */
        "umulh	x14, x6, x9\n\t"
        "mul	x13, x6, x9\n\t"
        /*  A[0] * A[2] */
        "mul	x3, x6, x8\n\t"
        "adds	x12, x12, x3\n\t"
        "umulh	x4, x6, x8\n\t"
        "adcs	x13, x13, x4\n\t"
        /*  A[1] * A[3] */
        "mul	x3, x7, x9\n\t"
        "adcs	x14, x14, x3\n\t"
        "umulh	x15, x7, x9\n\t"
        "adc	x15, x15, xzr\n\t"
        /*  A[1] * A[2] */
        "mul	x3, x7, x8\n\t"
        "adds	x13, x13, x3\n\t"
        "umulh	x4, x7, x8\n\t"
        "adcs	x14, x14, x4\n\t"
        /*  A[2] * A[3] */
        "mul	x3, x8, x9\n\t"
        "adcs	x15, x15, x3\n\t"
        "umulh	x16, x8, x9\n\t"
        "adc	x16, x16, xzr\n\t"
        /* Double */
        "adds	x11, x11, x11\n\t"
        "adcs	x12, x12, x12\n\t"
        "adcs	x13, x13, x13\n\t"
        "adcs	x14, x14, x14\n\t"
        "adcs	x15, x15, x15\n\t"
        "adcs	x16, x16, x16\n\t"
        "adc	x17, xzr, xzr\n\t"
        /*  A[0] * A[0] */
        "umulh	x4, x6, x6\n\t"
        "mul	x10, x6, x6\n\t"
        /*  A[1] * A[1] */
        "mul	x3, x7, x7\n\t"
        "adds	x11, x11, x4\n\t"
        "umulh	x4, x7, x7\n\t"
        "adcs	x12, x12, x3\n\t"
        /*  A[2] * A[2] */
        "mul	x3, x8, x8\n\t"
        "adcs	x13, x13, x4\n\t"
        "umulh	x4, x8, x8\n\t"
        "adcs	x14, x14, x3\n\t"
        /*  A[3] * A[3] */
        "mul	x3, x9, x9\n\t"
        "adcs	x15, x15, x4\n\t"
        "umulh	x4, x9, x9\n\t"
        "adcs	x16, x16, x3\n\t"
        "adc	x17, x17, x4\n\t"
        /* Reduce */
        "mov	x3, #38\n\t"
        "mul	x4, x3, x17\n\t"
        "adds	x13, x13, x4\n\t"
        "umulh	x5, x3, x17\n\t"
        "adc	x5, x5, xzr\n\t"
        "mov	x3, #19\n\t"
        "extr	x5, x5, x13, #63\n\t"
        "mul	x5, x5, x3\n\t"
        "and	x13, x13, #0x7fffffffffffffff\n\t"
        "mov	x3, #38\n\t"
        "mul	x4, x3, x14\n\t"
        "adds	x10, x10, x4\n\t"
        "umulh	x14, x3, x14\n\t"
        "mul	x4, x3, x15\n\t"
        "adcs	x11, x11, x4\n\t"
        "umulh	x15, x3, x15\n\t"
        "mul	x4, x3, x16\n\t"
        "adcs	x12, x12, x4\n\t"
        "umulh	x16, x3, x16\n\t"
        "adc	x13, x13, xzr\n\t"
        /*  Add high product results in */
        "adds	x6, x10, x5\n\t"
        "adcs	x7, x11, x14\n\t"
        "adcs	x8, x12, x15\n\t"
        "adc	x9, x13, x16\n\t"
        "subs	x20, x20, #1\n\t"
        "b.ne	L_fe_invert1_%=\n\t"
        /* Store */
        "stp	x6, x7, [x29, #80]\n\t"
        "stp	x8, x9, [x29, #96]\n\t"
#ifndef NDEBUG
        "add	x0, x29, #48\n\t"
#endif /* !NDEBUG */
        "add	x1, x29, #0x50\n\t"
        "add	x2, x29, #48\n\t"
#ifndef __APPLE__
        "bl	fe_mul\n\t"
#else
        "bl	_fe_mul\n\t"
#endif /* __APPLE__ */
        /* Loop: 10 times */
        "mov	x20, #10\n\t"
        "ldp	x6, x7, [x29, #48]\n\t"
        "ldp	x8, x9, [x29, #64]\n\t"
        "\n"
    "L_fe_invert2_%=: \n\t"
        /* Square */
        /*  A[0] * A[1] */
        "umulh	x12, x6, x7\n\t"
        "mul	x11, x6, x7\n\t"
        /*  A[0] * A[3] */
        "umulh	x14, x6, x9\n\t"
        "mul	x13, x6, x9\n\t"
        /*  A[0] * A[2] */
        "mul	x3, x6, x8\n\t"
        "adds	x12, x12, x3\n\t"
        "umulh	x4, x6, x8\n\t"
        "adcs	x13, x13, x4\n\t"
        /*  A[1] * A[3] */
        "mul	x3, x7, x9\n\t"
        "adcs	x14, x14, x3\n\t"
        "umulh	x15, x7, x9\n\t"
        "adc	x15, x15, xzr\n\t"
        /*  A[1] * A[2] */
        "mul	x3, x7, x8\n\t"
        "adds	x13, x13, x3\n\t"
        "umulh	x4, x7, x8\n\t"
        "adcs	x14, x14, x4\n\t"
        /*  A[2] * A[3] */
        "mul	x3, x8, x9\n\t"
        "adcs	x15, x15, x3\n\t"
        "umulh	x16, x8, x9\n\t"
        "adc	x16, x16, xzr\n\t"
        /* Double */
        "adds	x11, x11, x11\n\t"
        "adcs	x12, x12, x12\n\t"
        "adcs	x13, x13, x13\n\t"
        "adcs	x14, x14, x14\n\t"
        "adcs	x15, x15, x15\n\t"
        "adcs	x16, x16, x16\n\t"
        "adc	x17, xzr, xzr\n\t"
        /*  A[0] * A[0] */
        "umulh	x4, x6, x6\n\t"
        "mul	x10, x6, x6\n\t"
        /*  A[1] * A[1] */
        "mul	x3, x7, x7\n\t"
        "adds	x11, x11, x4\n\t"
        "umulh	x4, x7, x7\n\t"
        "adcs	x12, x12, x3\n\t"
        /*  A[2] * A[2] */
        "mul	x3, x8, x8\n\t"
        "adcs	x13, x13, x4\n\t"
        "umulh	x4, x8, x8\n\t"
        "adcs	x14, x14, x3\n\t"
        /*  A[3] * A[3] */
        "mul	x3, x9, x9\n\t"
        "adcs	x15, x15, x4\n\t"
        "umulh	x4, x9, x9\n\t"
        "adcs	x16, x16, x3\n\t"
        "adc	x17, x17, x4\n\t"
        /* Reduce */
        "mov	x3, #38\n\t"
        "mul	x4, x3, x17\n\t"
        "adds	x13, x13, x4\n\t"
        "umulh	x5, x3, x17\n\t"
        "adc	x5, x5, xzr\n\t"
        "mov	x3, #19\n\t"
        "extr	x5, x5, x13, #63\n\t"
        "mul	x5, x5, x3\n\t"
        "and	x13, x13, #0x7fffffffffffffff\n\t"
        "mov	x3, #38\n\t"
        "mul	x4, x3, x14\n\t"
        "adds	x10, x10, x4\n\t"
        "umulh	x14, x3, x14\n\t"
        "mul	x4, x3, x15\n\t"
        "adcs	x11, x11, x4\n\t"
        "umulh	x15, x3, x15\n\t"
        "mul	x4, x3, x16\n\t"
        "adcs	x12, x12, x4\n\t"
        "umulh	x16, x3, x16\n\t"
        "adc	x13, x13, xzr\n\t"
        /*  Add high product results in */
        "adds	x6, x10, x5\n\t"
        "adcs	x7, x11, x14\n\t"
        "adcs	x8, x12, x15\n\t"
        "adc	x9, x13, x16\n\t"
        "subs	x20, x20, #1\n\t"
        "b.ne	L_fe_invert2_%=\n\t"
        /* Store */
        "stp	x6, x7, [x29, #80]\n\t"
        "stp	x8, x9, [x29, #96]\n\t"
        "add	x0, x29, #0x50\n\t"
#ifndef NDEBUG
        "add	x1, x29, #0x50\n\t"
#endif /* !NDEBUG */
        "add	x2, x29, #48\n\t"
#ifndef __APPLE__
        "bl	fe_mul\n\t"
#else
        "bl	_fe_mul\n\t"
#endif /* __APPLE__ */
        /* Loop: 20 times */
        "mov	x20, #20\n\t"
        "ldp	x6, x7, [x29, #80]\n\t"
        "ldp	x8, x9, [x29, #96]\n\t"
        "\n"
    "L_fe_invert3_%=: \n\t"
        /* Square */
        /*  A[0] * A[1] */
        "umulh	x12, x6, x7\n\t"
        "mul	x11, x6, x7\n\t"
        /*  A[0] * A[3] */
        "umulh	x14, x6, x9\n\t"
        "mul	x13, x6, x9\n\t"
        /*  A[0] * A[2] */
        "mul	x3, x6, x8\n\t"
        "adds	x12, x12, x3\n\t"
        "umulh	x4, x6, x8\n\t"
        "adcs	x13, x13, x4\n\t"
        /*  A[1] * A[3] */
        "mul	x3, x7, x9\n\t"
        "adcs	x14, x14, x3\n\t"
        "umulh	x15, x7, x9\n\t"
        "adc	x15, x15, xzr\n\t"
        /*  A[1] * A[2] */
        "mul	x3, x7, x8\n\t"
        "adds	x13, x13, x3\n\t"
        "umulh	x4, x7, x8\n\t"
        "adcs	x14, x14, x4\n\t"
        /*  A[2] * A[3] */
        "mul	x3, x8, x9\n\t"
        "adcs	x15, x15, x3\n\t"
        "umulh	x16, x8, x9\n\t"
        "adc	x16, x16, xzr\n\t"
        /* Double */
        "adds	x11, x11, x11\n\t"
        "adcs	x12, x12, x12\n\t"
        "adcs	x13, x13, x13\n\t"
        "adcs	x14, x14, x14\n\t"
        "adcs	x15, x15, x15\n\t"
        "adcs	x16, x16, x16\n\t"
        "adc	x17, xzr, xzr\n\t"
        /*  A[0] * A[0] */
        "umulh	x4, x6, x6\n\t"
        "mul	x10, x6, x6\n\t"
        /*  A[1] * A[1] */
        "mul	x3, x7, x7\n\t"
        "adds	x11, x11, x4\n\t"
        "umulh	x4, x7, x7\n\t"
        "adcs	x12, x12, x3\n\t"
        /*  A[2] * A[2] */
        "mul	x3, x8, x8\n\t"
        "adcs	x13, x13, x4\n\t"
        "umulh	x4, x8, x8\n\t"
        "adcs	x14, x14, x3\n\t"
        /*  A[3] * A[3] */
        "mul	x3, x9, x9\n\t"
        "adcs	x15, x15, x4\n\t"
        "umulh	x4, x9, x9\n\t"
        "adcs	x16, x16, x3\n\t"
        "adc	x17, x17, x4\n\t"
        /* Reduce */
        "mov	x3, #38\n\t"
        "mul	x4, x3, x17\n\t"
        "adds	x13, x13, x4\n\t"
        "umulh	x5, x3, x17\n\t"
        "adc	x5, x5, xzr\n\t"
        "mov	x3, #19\n\t"
        "extr	x5, x5, x13, #63\n\t"
        "mul	x5, x5, x3\n\t"
        "and	x13, x13, #0x7fffffffffffffff\n\t"
        "mov	x3, #38\n\t"
        "mul	x4, x3, x14\n\t"
        "adds	x10, x10, x4\n\t"
        "umulh	x14, x3, x14\n\t"
        "mul	x4, x3, x15\n\t"
        "adcs	x11, x11, x4\n\t"
        "umulh	x15, x3, x15\n\t"
        "mul	x4, x3, x16\n\t"
        "adcs	x12, x12, x4\n\t"
        "umulh	x16, x3, x16\n\t"
        "adc	x13, x13, xzr\n\t"
        /*  Add high product results in */
        "adds	x6, x10, x5\n\t"
        "adcs	x7, x11, x14\n\t"
        "adcs	x8, x12, x15\n\t"
        "adc	x9, x13, x16\n\t"
        "subs	x20, x20, #1\n\t"
        "b.ne	L_fe_invert3_%=\n\t"
        /* Store */
        "stp	x6, x7, [x29, #112]\n\t"
        "stp	x8, x9, [x29, #128]\n\t"
#ifndef NDEBUG
        "add	x0, x29, #0x50\n\t"
#endif /* !NDEBUG */
        "add	x1, x29, #0x70\n\t"
        "add	x2, x29, #0x50\n\t"
#ifndef __APPLE__
        "bl	fe_mul\n\t"
#else
        "bl	_fe_mul\n\t"
#endif /* __APPLE__ */
        /* Loop: 10 times */
        "mov	x20, #10\n\t"
        "ldp	x6, x7, [x29, #80]\n\t"
        "ldp	x8, x9, [x29, #96]\n\t"
        "\n"
    "L_fe_invert4_%=: \n\t"
        /* Square */
        /*  A[0] * A[1] */
        "umulh	x12, x6, x7\n\t"
        "mul	x11, x6, x7\n\t"
        /*  A[0] * A[3] */
        "umulh	x14, x6, x9\n\t"
        "mul	x13, x6, x9\n\t"
        /*  A[0] * A[2] */
        "mul	x3, x6, x8\n\t"
        "adds	x12, x12, x3\n\t"
        "umulh	x4, x6, x8\n\t"
        "adcs	x13, x13, x4\n\t"
        /*  A[1] * A[3] */
        "mul	x3, x7, x9\n\t"
        "adcs	x14, x14, x3\n\t"
        "umulh	x15, x7, x9\n\t"
        "adc	x15, x15, xzr\n\t"
        /*  A[1] * A[2] */
        "mul	x3, x7, x8\n\t"
        "adds	x13, x13, x3\n\t"
        "umulh	x4, x7, x8\n\t"
        "adcs	x14, x14, x4\n\t"
        /*  A[2] * A[3] */
        "mul	x3, x8, x9\n\t"
        "adcs	x15, x15, x3\n\t"
        "umulh	x16, x8, x9\n\t"
        "adc	x16, x16, xzr\n\t"
        /* Double */
        "adds	x11, x11, x11\n\t"
        "adcs	x12, x12, x12\n\t"
        "adcs	x13, x13, x13\n\t"
        "adcs	x14, x14, x14\n\t"
        "adcs	x15, x15, x15\n\t"
        "adcs	x16, x16, x16\n\t"
        "adc	x17, xzr, xzr\n\t"
        /*  A[0] * A[0] */
        "umulh	x4, x6, x6\n\t"
        "mul	x10, x6, x6\n\t"
        /*  A[1] * A[1] */
        "mul	x3, x7, x7\n\t"
        "adds	x11, x11, x4\n\t"
        "umulh	x4, x7, x7\n\t"
        "adcs	x12, x12, x3\n\t"
        /*  A[2] * A[2] */
        "mul	x3, x8, x8\n\t"
        "adcs	x13, x13, x4\n\t"
        "umulh	x4, x8, x8\n\t"
        "adcs	x14, x14, x3\n\t"
        /*  A[3] * A[3] */
        "mul	x3, x9, x9\n\t"
        "adcs	x15, x15, x4\n\t"
        "umulh	x4, x9, x9\n\t"
        "adcs	x16, x16, x3\n\t"
        "adc	x17, x17, x4\n\t"
        /* Reduce */
        "mov	x3, #38\n\t"
        "mul	x4, x3, x17\n\t"
        "adds	x13, x13, x4\n\t"
        "umulh	x5, x3, x17\n\t"
        "adc	x5, x5, xzr\n\t"
        "mov	x3, #19\n\t"
        "extr	x5, x5, x13, #63\n\t"
        "mul	x5, x5, x3\n\t"
        "and	x13, x13, #0x7fffffffffffffff\n\t"
        "mov	x3, #38\n\t"
        "mul	x4, x3, x14\n\t"
        "adds	x10, x10, x4\n\t"
        "umulh	x14, x3, x14\n\t"
        "mul	x4, x3, x15\n\t"
        "adcs	x11, x11, x4\n\t"
        "umulh	x15, x3, x15\n\t"
        "mul	x4, x3, x16\n\t"
        "adcs	x12, x12, x4\n\t"
        "umulh	x16, x3, x16\n\t"
        "adc	x13, x13, xzr\n\t"
        /*  Add high product results in */
        "adds	x6, x10, x5\n\t"
        "adcs	x7, x11, x14\n\t"
        "adcs	x8, x12, x15\n\t"
        "adc	x9, x13, x16\n\t"
        "subs	x20, x20, #1\n\t"
        "b.ne	L_fe_invert4_%=\n\t"
        /* Store */
        "stp	x6, x7, [x29, #80]\n\t"
        "stp	x8, x9, [x29, #96]\n\t"
        "add	x0, x29, #48\n\t"
        "add	x1, x29, #0x50\n\t"
        "add	x2, x29, #48\n\t"
#ifndef __APPLE__
        "bl	fe_mul\n\t"
#else
        "bl	_fe_mul\n\t"
#endif /* __APPLE__ */
        /* Loop: 50 times */
        "mov	x20, #50\n\t"
        "ldp	x6, x7, [x29, #48]\n\t"
        "ldp	x8, x9, [x29, #64]\n\t"
        "\n"
    "L_fe_invert5_%=: \n\t"
        /* Square */
        /*  A[0] * A[1] */
        "umulh	x12, x6, x7\n\t"
        "mul	x11, x6, x7\n\t"
        /*  A[0] * A[3] */
        "umulh	x14, x6, x9\n\t"
        "mul	x13, x6, x9\n\t"
        /*  A[0] * A[2] */
        "mul	x3, x6, x8\n\t"
        "adds	x12, x12, x3\n\t"
        "umulh	x4, x6, x8\n\t"
        "adcs	x13, x13, x4\n\t"
        /*  A[1] * A[3] */
        "mul	x3, x7, x9\n\t"
        "adcs	x14, x14, x3\n\t"
        "umulh	x15, x7, x9\n\t"
        "adc	x15, x15, xzr\n\t"
        /*  A[1] * A[2] */
        "mul	x3, x7, x8\n\t"
        "adds	x13, x13, x3\n\t"
        "umulh	x4, x7, x8\n\t"
        "adcs	x14, x14, x4\n\t"
        /*  A[2] * A[3] */
        "mul	x3, x8, x9\n\t"
        "adcs	x15, x15, x3\n\t"
        "umulh	x16, x8, x9\n\t"
        "adc	x16, x16, xzr\n\t"
        /* Double */
        "adds	x11, x11, x11\n\t"
        "adcs	x12, x12, x12\n\t"
        "adcs	x13, x13, x13\n\t"
        "adcs	x14, x14, x14\n\t"
        "adcs	x15, x15, x15\n\t"
        "adcs	x16, x16, x16\n\t"
        "adc	x17, xzr, xzr\n\t"
        /*  A[0] * A[0] */
        "umulh	x4, x6, x6\n\t"
        "mul	x10, x6, x6\n\t"
        /*  A[1] * A[1] */
        "mul	x3, x7, x7\n\t"
        "adds	x11, x11, x4\n\t"
        "umulh	x4, x7, x7\n\t"
        "adcs	x12, x12, x3\n\t"
        /*  A[2] * A[2] */
        "mul	x3, x8, x8\n\t"
        "adcs	x13, x13, x4\n\t"
        "umulh	x4, x8, x8\n\t"
        "adcs	x14, x14, x3\n\t"
        /*  A[3] * A[3] */
        "mul	x3, x9, x9\n\t"
        "adcs	x15, x15, x4\n\t"
        "umulh	x4, x9, x9\n\t"
        "adcs	x16, x16, x3\n\t"
        "adc	x17, x17, x4\n\t"
        /* Reduce */
        "mov	x3, #38\n\t"
        "mul	x4, x3, x17\n\t"
        "adds	x13, x13, x4\n\t"
        "umulh	x5, x3, x17\n\t"
        "adc	x5, x5, xzr\n\t"
        "mov	x3, #19\n\t"
        "extr	x5, x5, x13, #63\n\t"
        "mul	x5, x5, x3\n\t"
        "and	x13, x13, #0x7fffffffffffffff\n\t"
        "mov	x3, #38\n\t"
        "mul	x4, x3, x14\n\t"
        "adds	x10, x10, x4\n\t"
        "umulh	x14, x3, x14\n\t"
        "mul	x4, x3, x15\n\t"
        "adcs	x11, x11, x4\n\t"
        "umulh	x15, x3, x15\n\t"
        "mul	x4, x3, x16\n\t"
        "adcs	x12, x12, x4\n\t"
        "umulh	x16, x3, x16\n\t"
        "adc	x13, x13, xzr\n\t"
        /*  Add high product results in */
        "adds	x6, x10, x5\n\t"
        "adcs	x7, x11, x14\n\t"
        "adcs	x8, x12, x15\n\t"
        "adc	x9, x13, x16\n\t"
        "subs	x20, x20, #1\n\t"
        "b.ne	L_fe_invert5_%=\n\t"
        /* Store */
        "stp	x6, x7, [x29, #80]\n\t"
        "stp	x8, x9, [x29, #96]\n\t"
        "add	x0, x29, #0x50\n\t"
#ifndef NDEBUG
        "add	x1, x29, #0x50\n\t"
#endif /* !NDEBUG */
        "add	x2, x29, #48\n\t"
#ifndef __APPLE__
        "bl	fe_mul\n\t"
#else
        "bl	_fe_mul\n\t"
#endif /* __APPLE__ */
        /* Loop: 100 times */
        "mov	x20, #0x64\n\t"
        "ldp	x6, x7, [x29, #80]\n\t"
        "ldp	x8, x9, [x29, #96]\n\t"
        "\n"
    "L_fe_invert6_%=: \n\t"
        /* Square */
        /*  A[0] * A[1] */
        "umulh	x12, x6, x7\n\t"
        "mul	x11, x6, x7\n\t"
        /*  A[0] * A[3] */
        "umulh	x14, x6, x9\n\t"
        "mul	x13, x6, x9\n\t"
        /*  A[0] * A[2] */
        "mul	x3, x6, x8\n\t"
        "adds	x12, x12, x3\n\t"
        "umulh	x4, x6, x8\n\t"
        "adcs	x13, x13, x4\n\t"
        /*  A[1] * A[3] */
        "mul	x3, x7, x9\n\t"
        "adcs	x14, x14, x3\n\t"
        "umulh	x15, x7, x9\n\t"
        "adc	x15, x15, xzr\n\t"
        /*  A[1] * A[2] */
        "mul	x3, x7, x8\n\t"
        "adds	x13, x13, x3\n\t"
        "umulh	x4, x7, x8\n\t"
        "adcs	x14, x14, x4\n\t"
        /*  A[2] * A[3] */
        "mul	x3, x8, x9\n\t"
        "adcs	x15, x15, x3\n\t"
        "umulh	x16, x8, x9\n\t"
        "adc	x16, x16, xzr\n\t"
        /* Double */
        "adds	x11, x11, x11\n\t"
        "adcs	x12, x12, x12\n\t"
        "adcs	x13, x13, x13\n\t"
        "adcs	x14, x14, x14\n\t"
        "adcs	x15, x15, x15\n\t"
        "adcs	x16, x16, x16\n\t"
        "adc	x17, xzr, xzr\n\t"
        /*  A[0] * A[0] */
        "umulh	x4, x6, x6\n\t"
        "mul	x10, x6, x6\n\t"
        /*  A[1] * A[1] */
        "mul	x3, x7, x7\n\t"
        "adds	x11, x11, x4\n\t"
        "umulh	x4, x7, x7\n\t"
        "adcs	x12, x12, x3\n\t"
        /*  A[2] * A[2] */
        "mul	x3, x8, x8\n\t"
        "adcs	x13, x13, x4\n\t"
        "umulh	x4, x8, x8\n\t"
        "adcs	x14, x14, x3\n\t"
        /*  A[3] * A[3] */
        "mul	x3, x9, x9\n\t"
        "adcs	x15, x15, x4\n\t"
        "umulh	x4, x9, x9\n\t"
        "adcs	x16, x16, x3\n\t"
        "adc	x17, x17, x4\n\t"
        /* Reduce */
        "mov	x3, #38\n\t"
        "mul	x4, x3, x17\n\t"
        "adds	x13, x13, x4\n\t"
        "umulh	x5, x3, x17\n\t"
        "adc	x5, x5, xzr\n\t"
        "mov	x3, #19\n\t"
        "extr	x5, x5, x13, #63\n\t"
        "mul	x5, x5, x3\n\t"
        "and	x13, x13, #0x7fffffffffffffff\n\t"
        "mov	x3, #38\n\t"
        "mul	x4, x3, x14\n\t"
        "adds	x10, x10, x4\n\t"
        "umulh	x14, x3, x14\n\t"
        "mul	x4, x3, x15\n\t"
        "adcs	x11, x11, x4\n\t"
        "umulh	x15, x3, x15\n\t"
        "mul	x4, x3, x16\n\t"
        "adcs	x12, x12, x4\n\t"
        "umulh	x16, x3, x16\n\t"
        "adc	x13, x13, xzr\n\t"
        /*  Add high product results in */
        "adds	x6, x10, x5\n\t"
        "adcs	x7, x11, x14\n\t"
        "adcs	x8, x12, x15\n\t"
        "adc	x9, x13, x16\n\t"
        "subs	x20, x20, #1\n\t"
        "b.ne	L_fe_invert6_%=\n\t"
        /* Store */
        "stp	x6, x7, [x29, #112]\n\t"
        "stp	x8, x9, [x29, #128]\n\t"
#ifndef NDEBUG
        "add	x0, x29, #0x50\n\t"
#endif /* !NDEBUG */
        "add	x1, x29, #0x70\n\t"
        "add	x2, x29, #0x50\n\t"
#ifndef __APPLE__
        "bl	fe_mul\n\t"
#else
        "bl	_fe_mul\n\t"
#endif /* __APPLE__ */
        /* Loop: 50 times */
        "mov	x20, #50\n\t"
        "ldp	x6, x7, [x29, #80]\n\t"
        "ldp	x8, x9, [x29, #96]\n\t"
        "\n"
    "L_fe_invert7_%=: \n\t"
        /* Square */
        /*  A[0] * A[1] */
        "umulh	x12, x6, x7\n\t"
        "mul	x11, x6, x7\n\t"
        /*  A[0] * A[3] */
        "umulh	x14, x6, x9\n\t"
        "mul	x13, x6, x9\n\t"
        /*  A[0] * A[2] */
        "mul	x3, x6, x8\n\t"
        "adds	x12, x12, x3\n\t"
        "umulh	x4, x6, x8\n\t"
        "adcs	x13, x13, x4\n\t"
        /*  A[1] * A[3] */
        "mul	x3, x7, x9\n\t"
        "adcs	x14, x14, x3\n\t"
        "umulh	x15, x7, x9\n\t"
        "adc	x15, x15, xzr\n\t"
        /*  A[1] * A[2] */
        "mul	x3, x7, x8\n\t"
        "adds	x13, x13, x3\n\t"
        "umulh	x4, x7, x8\n\t"
        "adcs	x14, x14, x4\n\t"
        /*  A[2] * A[3] */
        "mul	x3, x8, x9\n\t"
        "adcs	x15, x15, x3\n\t"
        "umulh	x16, x8, x9\n\t"
        "adc	x16, x16, xzr\n\t"
        /* Double */
        "adds	x11, x11, x11\n\t"
        "adcs	x12, x12, x12\n\t"
        "adcs	x13, x13, x13\n\t"
        "adcs	x14, x14, x14\n\t"
        "adcs	x15, x15, x15\n\t"
        "adcs	x16, x16, x16\n\t"
        "adc	x17, xzr, xzr\n\t"
        /*  A[0] * A[0] */
        "umulh	x4, x6, x6\n\t"
        "mul	x10, x6, x6\n\t"
        /*  A[1] * A[1] */
        "mul	x3, x7, x7\n\t"
        "adds	x11, x11, x4\n\t"
        "umulh	x4, x7, x7\n\t"
        "adcs	x12, x12, x3\n\t"
        /*  A[2] * A[2] */
        "mul	x3, x8, x8\n\t"
        "adcs	x13, x13, x4\n\t"
        "umulh	x4, x8, x8\n\t"
        "adcs	x14, x14, x3\n\t"
        /*  A[3] * A[3] */
        "mul	x3, x9, x9\n\t"
        "adcs	x15, x15, x4\n\t"
        "umulh	x4, x9, x9\n\t"
        "adcs	x16, x16, x3\n\t"
        "adc	x17, x17, x4\n\t"
        /* Reduce */
        "mov	x3, #38\n\t"
        "mul	x4, x3, x17\n\t"
        "adds	x13, x13, x4\n\t"
        "umulh	x5, x3, x17\n\t"
        "adc	x5, x5, xzr\n\t"
        "mov	x3, #19\n\t"
        "extr	x5, x5, x13, #63\n\t"
        "mul	x5, x5, x3\n\t"
        "and	x13, x13, #0x7fffffffffffffff\n\t"
        "mov	x3, #38\n\t"
        "mul	x4, x3, x14\n\t"
        "adds	x10, x10, x4\n\t"
        "umulh	x14, x3, x14\n\t"
        "mul	x4, x3, x15\n\t"
        "adcs	x11, x11, x4\n\t"
        "umulh	x15, x3, x15\n\t"
        "mul	x4, x3, x16\n\t"
        "adcs	x12, x12, x4\n\t"
        "umulh	x16, x3, x16\n\t"
        "adc	x13, x13, xzr\n\t"
        /*  Add high product results in */
        "adds	x6, x10, x5\n\t"
        "adcs	x7, x11, x14\n\t"
        "adcs	x8, x12, x15\n\t"
        "adc	x9, x13, x16\n\t"
        "subs	x20, x20, #1\n\t"
        "b.ne	L_fe_invert7_%=\n\t"
        /* Store */
        "stp	x6, x7, [x29, #80]\n\t"
        "stp	x8, x9, [x29, #96]\n\t"
        "add	x0, x29, #48\n\t"
        "add	x1, x29, #0x50\n\t"
        "add	x2, x29, #48\n\t"
#ifndef __APPLE__
        "bl	fe_mul\n\t"
#else
        "bl	_fe_mul\n\t"
#endif /* __APPLE__ */
        /* Loop: 5 times */
        "mov	x20, #5\n\t"
        "ldp	x6, x7, [x29, #48]\n\t"
        "ldp	x8, x9, [x29, #64]\n\t"
        "\n"
    "L_fe_invert8_%=: \n\t"
        /* Square */
        /*  A[0] * A[1] */
        "umulh	x12, x6, x7\n\t"
        "mul	x11, x6, x7\n\t"
        /*  A[0] * A[3] */
        "umulh	x14, x6, x9\n\t"
        "mul	x13, x6, x9\n\t"
        /*  A[0] * A[2] */
        "mul	x3, x6, x8\n\t"
        "adds	x12, x12, x3\n\t"
        "umulh	x4, x6, x8\n\t"
        "adcs	x13, x13, x4\n\t"
        /*  A[1] * A[3] */
        "mul	x3, x7, x9\n\t"
        "adcs	x14, x14, x3\n\t"
        "umulh	x15, x7, x9\n\t"
        "adc	x15, x15, xzr\n\t"
        /*  A[1] * A[2] */
        "mul	x3, x7, x8\n\t"
        "adds	x13, x13, x3\n\t"
        "umulh	x4, x7, x8\n\t"
        "adcs	x14, x14, x4\n\t"
        /*  A[2] * A[3] */
        "mul	x3, x8, x9\n\t"
        "adcs	x15, x15, x3\n\t"
        "umulh	x16, x8, x9\n\t"
        "adc	x16, x16, xzr\n\t"
        /* Double */
        "adds	x11, x11, x11\n\t"
        "adcs	x12, x12, x12\n\t"
        "adcs	x13, x13, x13\n\t"
        "adcs	x14, x14, x14\n\t"
        "adcs	x15, x15, x15\n\t"
        "adcs	x16, x16, x16\n\t"
        "adc	x17, xzr, xzr\n\t"
        /*  A[0] * A[0] */
        "umulh	x4, x6, x6\n\t"
        "mul	x10, x6, x6\n\t"
        /*  A[1] * A[1] */
        "mul	x3, x7, x7\n\t"
        "adds	x11, x11, x4\n\t"
        "umulh	x4, x7, x7\n\t"
        "adcs	x12, x12, x3\n\t"
        /*  A[2] * A[2] */
        "mul	x3, x8, x8\n\t"
        "adcs	x13, x13, x4\n\t"
        "umulh	x4, x8, x8\n\t"
        "adcs	x14, x14, x3\n\t"
        /*  A[3] * A[3] */
        "mul	x3, x9, x9\n\t"
        "adcs	x15, x15, x4\n\t"
        "umulh	x4, x9, x9\n\t"
        "adcs	x16, x16, x3\n\t"
        "adc	x17, x17, x4\n\t"
        /* Reduce */
        "mov	x3, #38\n\t"
        "mul	x4, x3, x17\n\t"
        "adds	x13, x13, x4\n\t"
        "umulh	x5, x3, x17\n\t"
        "adc	x5, x5, xzr\n\t"
        "mov	x3, #19\n\t"
        "extr	x5, x5, x13, #63\n\t"
        "mul	x5, x5, x3\n\t"
        "and	x13, x13, #0x7fffffffffffffff\n\t"
        "mov	x3, #38\n\t"
        "mul	x4, x3, x14\n\t"
        "adds	x10, x10, x4\n\t"
        "umulh	x14, x3, x14\n\t"
        "mul	x4, x3, x15\n\t"
        "adcs	x11, x11, x4\n\t"
        "umulh	x15, x3, x15\n\t"
        "mul	x4, x3, x16\n\t"
        "adcs	x12, x12, x4\n\t"
        "umulh	x16, x3, x16\n\t"
        "adc	x13, x13, xzr\n\t"
        /*  Add high product results in */
        "adds	x6, x10, x5\n\t"
        "adcs	x7, x11, x14\n\t"
        "adcs	x8, x12, x15\n\t"
        "adc	x9, x13, x16\n\t"
        "subs	x20, x20, #1\n\t"
        "b.ne	L_fe_invert8_%=\n\t"
        /* Store */
        "stp	x6, x7, [x29, #48]\n\t"
        "stp	x8, x9, [x29, #64]\n\t"
        "ldr	x0, [x29, #144]\n\t"
        "add	x1, x29, #48\n\t"
        "add	x2, x29, #16\n\t"
#ifndef __APPLE__
        "bl	fe_mul\n\t"
#else
        "bl	_fe_mul\n\t"
#endif /* __APPLE__ */
        "ldp	x29, x30, [sp], #0xa0\n\t"
        : [r] "+r" (r)
        : [a] "r" (a)
        : "memory", "cc", "x2", "x20", "x3", "x4", "x5", "x6", "x7", "x8", "x9",
            "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17"
    );
}

int curve25519(byte* r, const byte* n, const byte* a)
{
    __asm__ __volatile__ (
        "stp	x29, x30, [sp, #-192]!\n\t"
        "add	x29, sp, #0\n\t"
        "mov	x23, xzr\n\t"
        "str	%x[r], [x29, #176]\n\t"
        "str	%x[a], [x29, #184]\n\t"
        "ldp	x6, x7, [%x[a]]\n\t"
        "ldp	x8, x9, [%x[a], #16]\n\t"
        "mov	x10, #1\n\t"
        "mov	x11, xzr\n\t"
        "mov	x12, xzr\n\t"
        "mov	x13, xzr\n\t"
        "stp	x10, x11, [%x[r]]\n\t"
        "stp	x12, x13, [%x[r], #16]\n\t"
        /* Set zero */
        "stp	xzr, xzr, [x29, #16]\n\t"
        "stp	xzr, xzr, [x29, #32]\n\t"
        "mov	x24, #0xfe\n\t"
        "\n"
    "L_curve25519_bits_%=: \n\t"
        "lsr	x3, x24, #6\n\t"
        "and	x4, x24, #63\n\t"
        "ldr	x5, [%x[n], x3, LSL 3]\n\t"
        "lsr	x5, x5, x4\n\t"
        "eor	x23, x23, x5\n\t"
        /* Conditional Swap */
        "subs	xzr, xzr, x23, lsl 63\n\t"
        "ldp	x25, x26, [x29, #16]\n\t"
        "ldp	x27, x28, [x29, #32]\n\t"
        "csel	x19, x25, x10, ne\n\t"
        "csel	x25, x10, x25, ne\n\t"
        "csel	x20, x26, x11, ne\n\t"
        "csel	x26, x11, x26, ne\n\t"
        "csel	x21, x27, x12, ne\n\t"
        "csel	x27, x12, x27, ne\n\t"
        "csel	x22, x28, x13, ne\n\t"
        "csel	x28, x13, x28, ne\n\t"
        /* Conditional Swap */
        "subs	xzr, xzr, x23, lsl 63\n\t"
        "ldp	x10, x11, [%x[r]]\n\t"
        "ldp	x12, x13, [%x[r], #16]\n\t"
        "csel	x14, x10, x6, ne\n\t"
        "csel	x10, x6, x10, ne\n\t"
        "csel	x15, x11, x7, ne\n\t"
        "csel	x11, x7, x11, ne\n\t"
        "csel	x16, x12, x8, ne\n\t"
        "csel	x12, x8, x12, ne\n\t"
        "csel	x17, x13, x9, ne\n\t"
        "csel	x13, x9, x13, ne\n\t"
        "mov	x23, x5\n\t"
        /* Add */
        "adds	x6, x10, x25\n\t"
        "adcs	x7, x11, x26\n\t"
        "adcs	x8, x12, x27\n\t"
        "adcs	x9, x13, x28\n\t"
        "cset	x5, cs\n\t"
        "mov	x3, #19\n\t"
        "extr	x5, x5, x9, #63\n\t"
        "mul	x3, x5, x3\n\t"
        /*   Sub modulus (if overflow) */
        "adds	x6, x6, x3\n\t"
        "adcs	x7, x7, xzr\n\t"
        "and	x9, x9, #0x7fffffffffffffff\n\t"
        "adcs	x8, x8, xzr\n\t"
        "adc	x9, x9, xzr\n\t"
        /* Sub */
        "subs	x25, x10, x25\n\t"
        "sbcs	x26, x11, x26\n\t"
        "sbcs	x27, x12, x27\n\t"
        "sbcs	x28, x13, x28\n\t"
        "csetm	x5, cc\n\t"
        "mov	x3, #-19\n\t"
        "extr	x5, x5, x28, #63\n\t"
        "mul	x3, x5, x3\n\t"
        /*   Add modulus (if underflow) */
        "subs	x25, x25, x3\n\t"
        "sbcs	x26, x26, xzr\n\t"
        "and	x28, x28, #0x7fffffffffffffff\n\t"
        "sbcs	x27, x27, xzr\n\t"
        "sbc	x28, x28, xzr\n\t"
        "stp	x25, x26, [x29, #80]\n\t"
        "stp	x27, x28, [x29, #96]\n\t"
        /* Add */
        "adds	x10, x14, x19\n\t"
        "adcs	x11, x15, x20\n\t"
        "adcs	x12, x16, x21\n\t"
        "adcs	x13, x17, x22\n\t"
        "cset	x5, cs\n\t"
        "mov	x3, #19\n\t"
        "extr	x5, x5, x13, #63\n\t"
        "mul	x3, x5, x3\n\t"
        /*   Sub modulus (if overflow) */
        "adds	x10, x10, x3\n\t"
        "adcs	x11, x11, xzr\n\t"
        "and	x13, x13, #0x7fffffffffffffff\n\t"
        "adcs	x12, x12, xzr\n\t"
        "adc	x13, x13, xzr\n\t"
        /* Sub */
        "subs	x14, x14, x19\n\t"
        "sbcs	x15, x15, x20\n\t"
        "sbcs	x16, x16, x21\n\t"
        "sbcs	x17, x17, x22\n\t"
        "csetm	x5, cc\n\t"
        "mov	x3, #-19\n\t"
        "extr	x5, x5, x17, #63\n\t"
        "mul	x3, x5, x3\n\t"
        /*   Add modulus (if underflow) */
        "subs	x14, x14, x3\n\t"
        "sbcs	x15, x15, xzr\n\t"
        "and	x17, x17, #0x7fffffffffffffff\n\t"
        "sbcs	x16, x16, xzr\n\t"
        "sbc	x17, x17, xzr\n\t"
        /* Multiply */
        /* A[0] * B[0] */
        "umulh	x20, x14, x6\n\t"
        "mul	x19, x14, x6\n\t"
        /* A[2] * B[0] */
        "umulh	x22, x16, x6\n\t"
        "mul	x21, x16, x6\n\t"
        /* A[1] * B[0] */
        "mul	x3, x15, x6\n\t"
        "adds	x20, x20, x3\n\t"
        "umulh	x4, x15, x6\n\t"
        "adcs	x21, x21, x4\n\t"
        /* A[1] * B[3] */
        "umulh	x26, x15, x9\n\t"
        "adc	x22, x22, xzr\n\t"
        "mul	x25, x15, x9\n\t"
        /* A[0] * B[1] */
        "mul	x3, x14, x7\n\t"
        "adds	x20, x20, x3\n\t"
        "umulh	x4, x14, x7\n\t"
        "adcs	x21, x21, x4\n\t"
        /* A[2] * B[1] */
        "mul	x3, x16, x7\n\t"
        "adcs	x22, x22, x3\n\t"
        "umulh	x4, x16, x7\n\t"
        "adcs	x25, x25, x4\n\t"
        "adc	x26, x26, xzr\n\t"
        /* A[1] * B[2] */
        "mul	x3, x15, x8\n\t"
        "adds	x22, x22, x3\n\t"
        "umulh	x4, x15, x8\n\t"
        "adcs	x25, x25, x4\n\t"
        "adcs	x26, x26, xzr\n\t"
        "adc	x27, xzr, xzr\n\t"
        /* A[0] * B[2] */
        "mul	x3, x14, x8\n\t"
        "adds	x21, x21, x3\n\t"
        "umulh	x4, x14, x8\n\t"
        "adcs	x22, x22, x4\n\t"
        "adcs	x25, x25, xzr\n\t"
        "adcs	x26, x26, xzr\n\t"
        "adc	x27, x27, xzr\n\t"
        /* A[1] * B[1] */
        "mul	x3, x15, x7\n\t"
        "adds	x21, x21, x3\n\t"
        "umulh	x4, x15, x7\n\t"
        "adcs	x22, x22, x4\n\t"
        /* A[3] * B[1] */
        "mul	x3, x17, x7\n\t"
        "adcs	x25, x25, x3\n\t"
        "umulh	x4, x17, x7\n\t"
        "adcs	x26, x26, x4\n\t"
        "adc	x27, x27, xzr\n\t"
        /* A[2] * B[2] */
        "mul	x3, x16, x8\n\t"
        "adds	x25, x25, x3\n\t"
        "umulh	x4, x16, x8\n\t"
        "adcs	x26, x26, x4\n\t"
        /* A[3] * B[3] */
        "mul	x3, x17, x9\n\t"
        "adcs	x27, x27, x3\n\t"
        "umulh	x28, x17, x9\n\t"
        "adc	x28, x28, xzr\n\t"
        /* A[0] * B[3] */
        "mul	x3, x14, x9\n\t"
        "adds	x22, x22, x3\n\t"
        "umulh	x4, x14, x9\n\t"
        "adcs	x25, x25, x4\n\t"
        /* A[2] * B[3] */
        "mul	x3, x16, x9\n\t"
        "adcs	x26, x26, x3\n\t"
        "umulh	x4, x16, x9\n\t"
        "adcs	x27, x27, x4\n\t"
        "adc	x28, x28, xzr\n\t"
        /* A[3] * B[0] */
        "mul	x3, x17, x6\n\t"
        "adds	x22, x22, x3\n\t"
        "umulh	x4, x17, x6\n\t"
        "adcs	x25, x25, x4\n\t"
        /* A[3] * B[2] */
        "mul	x3, x17, x8\n\t"
        "adcs	x26, x26, x3\n\t"
        "umulh	x4, x17, x8\n\t"
        "adcs	x27, x27, x4\n\t"
        "adc	x28, x28, xzr\n\t"
        /* Reduce */
        "mov	x3, #38\n\t"
        "mul	x4, x3, x28\n\t"
        "adds	x22, x22, x4\n\t"
        "umulh	x5, x3, x28\n\t"
        "adc	x5, x5, xzr\n\t"
        "mov	x3, #19\n\t"
        "extr	x5, x5, x22, #63\n\t"
        "mul	x5, x5, x3\n\t"
        "and	x22, x22, #0x7fffffffffffffff\n\t"
        "mov	x3, #38\n\t"
        "mul	x4, x3, x25\n\t"
        "adds	x19, x19, x4\n\t"
        "umulh	x25, x3, x25\n\t"
        "mul	x4, x3, x26\n\t"
        "adcs	x20, x20, x4\n\t"
        "umulh	x26, x3, x26\n\t"
        "mul	x4, x3, x27\n\t"
        "adcs	x21, x21, x4\n\t"
        "umulh	x27, x3, x27\n\t"
        "adc	x22, x22, xzr\n\t"
        /*  Add high product results in */
        "adds	x19, x19, x5\n\t"
        "adcs	x20, x20, x25\n\t"
        "adcs	x21, x21, x26\n\t"
        "adc	x22, x22, x27\n\t"
        /* Store */
        "stp	x19, x20, [x29, #48]\n\t"
        "stp	x21, x22, [x29, #64]\n\t"
        /* Multiply */
        "ldp	x25, x26, [x29, #80]\n\t"
        "ldp	x27, x28, [x29, #96]\n\t"
        /* A[0] * B[0] */
        "umulh	x20, x10, x25\n\t"
        "mul	x19, x10, x25\n\t"
        /* A[2] * B[0] */
        "umulh	x22, x12, x25\n\t"
        "mul	x21, x12, x25\n\t"
        /* A[1] * B[0] */
        "mul	x3, x11, x25\n\t"
        "adds	x20, x20, x3\n\t"
        "umulh	x4, x11, x25\n\t"
        "adcs	x21, x21, x4\n\t"
        /* A[1] * B[3] */
        "umulh	x15, x11, x28\n\t"
        "adc	x22, x22, xzr\n\t"
        "mul	x14, x11, x28\n\t"
        /* A[0] * B[1] */
        "mul	x3, x10, x26\n\t"
        "adds	x20, x20, x3\n\t"
        "umulh	x4, x10, x26\n\t"
        "adcs	x21, x21, x4\n\t"
        /* A[2] * B[1] */
        "mul	x3, x12, x26\n\t"
        "adcs	x22, x22, x3\n\t"
        "umulh	x4, x12, x26\n\t"
        "adcs	x14, x14, x4\n\t"
        "adc	x15, x15, xzr\n\t"
        /* A[1] * B[2] */
        "mul	x3, x11, x27\n\t"
        "adds	x22, x22, x3\n\t"
        "umulh	x4, x11, x27\n\t"
        "adcs	x14, x14, x4\n\t"
        "adcs	x15, x15, xzr\n\t"
        "adc	x16, xzr, xzr\n\t"
        /* A[0] * B[2] */
        "mul	x3, x10, x27\n\t"
        "adds	x21, x21, x3\n\t"
        "umulh	x4, x10, x27\n\t"
        "adcs	x22, x22, x4\n\t"
        "adcs	x14, x14, xzr\n\t"
        "adcs	x15, x15, xzr\n\t"
        "adc	x16, x16, xzr\n\t"
        /* A[1] * B[1] */
        "mul	x3, x11, x26\n\t"
        "adds	x21, x21, x3\n\t"
        "umulh	x4, x11, x26\n\t"
        "adcs	x22, x22, x4\n\t"
        /* A[3] * B[1] */
        "mul	x3, x13, x26\n\t"
        "adcs	x14, x14, x3\n\t"
        "umulh	x4, x13, x26\n\t"
        "adcs	x15, x15, x4\n\t"
        "adc	x16, x16, xzr\n\t"
        /* A[2] * B[2] */
        "mul	x3, x12, x27\n\t"
        "adds	x14, x14, x3\n\t"
        "umulh	x4, x12, x27\n\t"
        "adcs	x15, x15, x4\n\t"
        /* A[3] * B[3] */
        "mul	x3, x13, x28\n\t"
        "adcs	x16, x16, x3\n\t"
        "umulh	x17, x13, x28\n\t"
        "adc	x17, x17, xzr\n\t"
        /* A[0] * B[3] */
        "mul	x3, x10, x28\n\t"
        "adds	x22, x22, x3\n\t"
        "umulh	x4, x10, x28\n\t"
        "adcs	x14, x14, x4\n\t"
        /* A[2] * B[3] */
        "mul	x3, x12, x28\n\t"
        "adcs	x15, x15, x3\n\t"
        "umulh	x4, x12, x28\n\t"
        "adcs	x16, x16, x4\n\t"
        "adc	x17, x17, xzr\n\t"
        /* A[3] * B[0] */
        "mul	x3, x13, x25\n\t"
        "adds	x22, x22, x3\n\t"
        "umulh	x4, x13, x25\n\t"
        "adcs	x14, x14, x4\n\t"
        /* A[3] * B[2] */
        "mul	x3, x13, x27\n\t"
        "adcs	x15, x15, x3\n\t"
        "umulh	x4, x13, x27\n\t"
        "adcs	x16, x16, x4\n\t"
        "adc	x17, x17, xzr\n\t"
        /* Reduce */
        "mov	x3, #38\n\t"
        "mul	x4, x3, x17\n\t"
        "adds	x22, x22, x4\n\t"
        "umulh	x5, x3, x17\n\t"
        "adc	x5, x5, xzr\n\t"
        "mov	x3, #19\n\t"
        "extr	x5, x5, x22, #63\n\t"
        "mul	x5, x5, x3\n\t"
        "and	x22, x22, #0x7fffffffffffffff\n\t"
        "mov	x3, #38\n\t"
        "mul	x4, x3, x14\n\t"
        "adds	x19, x19, x4\n\t"
        "umulh	x14, x3, x14\n\t"
        "mul	x4, x3, x15\n\t"
        "adcs	x20, x20, x4\n\t"
        "umulh	x15, x3, x15\n\t"
        "mul	x4, x3, x16\n\t"
        "adcs	x21, x21, x4\n\t"
        "umulh	x16, x3, x16\n\t"
        "adc	x22, x22, xzr\n\t"
        /*  Add high product results in */
        "adds	x19, x19, x5\n\t"
        "adcs	x20, x20, x14\n\t"
        "adcs	x21, x21, x15\n\t"
        "adc	x22, x22, x16\n\t"
        /* Square */
        /*  A[0] * A[1] */
        "umulh	x12, x25, x26\n\t"
        "mul	x11, x25, x26\n\t"
        /*  A[0] * A[3] */
        "umulh	x14, x25, x28\n\t"
        "mul	x13, x25, x28\n\t"
        /*  A[0] * A[2] */
        "mul	x3, x25, x27\n\t"
        "adds	x12, x12, x3\n\t"
        "umulh	x4, x25, x27\n\t"
        "adcs	x13, x13, x4\n\t"
        /*  A[1] * A[3] */
        "mul	x3, x26, x28\n\t"
        "adcs	x14, x14, x3\n\t"
        "umulh	x15, x26, x28\n\t"
        "adc	x15, x15, xzr\n\t"
        /*  A[1] * A[2] */
        "mul	x3, x26, x27\n\t"
        "adds	x13, x13, x3\n\t"
        "umulh	x4, x26, x27\n\t"
        "adcs	x14, x14, x4\n\t"
        /*  A[2] * A[3] */
        "mul	x3, x27, x28\n\t"
        "adcs	x15, x15, x3\n\t"
        "umulh	x16, x27, x28\n\t"
        "adc	x16, x16, xzr\n\t"
        /* Double */
        "adds	x11, x11, x11\n\t"
        "adcs	x12, x12, x12\n\t"
        "adcs	x13, x13, x13\n\t"
        "adcs	x14, x14, x14\n\t"
        "adcs	x15, x15, x15\n\t"
        "adcs	x16, x16, x16\n\t"
        "adc	x17, xzr, xzr\n\t"
        /*  A[0] * A[0] */
        "umulh	x4, x25, x25\n\t"
        "mul	x10, x25, x25\n\t"
        /*  A[1] * A[1] */
        "mul	x3, x26, x26\n\t"
        "adds	x11, x11, x4\n\t"
        "umulh	x4, x26, x26\n\t"
        "adcs	x12, x12, x3\n\t"
        /*  A[2] * A[2] */
        "mul	x3, x27, x27\n\t"
        "adcs	x13, x13, x4\n\t"
        "umulh	x4, x27, x27\n\t"
        "adcs	x14, x14, x3\n\t"
        /*  A[3] * A[3] */
        "mul	x3, x28, x28\n\t"
        "adcs	x15, x15, x4\n\t"
        "umulh	x4, x28, x28\n\t"
        "adcs	x16, x16, x3\n\t"
        "adc	x17, x17, x4\n\t"
        /* Reduce */
        "mov	x3, #38\n\t"
        "mul	x4, x3, x17\n\t"
        "adds	x13, x13, x4\n\t"
        "umulh	x5, x3, x17\n\t"
        "adc	x5, x5, xzr\n\t"
        "mov	x3, #19\n\t"
        "extr	x5, x5, x13, #63\n\t"
        "mul	x5, x5, x3\n\t"
        "and	x13, x13, #0x7fffffffffffffff\n\t"
        "mov	x3, #38\n\t"
        "mul	x4, x3, x14\n\t"
        "adds	x10, x10, x4\n\t"
        "umulh	x14, x3, x14\n\t"
        "mul	x4, x3, x15\n\t"
        "adcs	x11, x11, x4\n\t"
        "umulh	x15, x3, x15\n\t"
        "mul	x4, x3, x16\n\t"
        "adcs	x12, x12, x4\n\t"
        "umulh	x16, x3, x16\n\t"
        "adc	x13, x13, xzr\n\t"
        /*  Add high product results in */
        "adds	x10, x10, x5\n\t"
        "adcs	x11, x11, x14\n\t"
        "adcs	x12, x12, x15\n\t"
        "adc	x13, x13, x16\n\t"
        /* Square */
        /*  A[0] * A[1] */
        "umulh	x16, x6, x7\n\t"
        "mul	x15, x6, x7\n\t"
        /*  A[0] * A[3] */
        "umulh	x25, x6, x9\n\t"
        "mul	x17, x6, x9\n\t"
        /*  A[0] * A[2] */
        "mul	x3, x6, x8\n\t"
        "adds	x16, x16, x3\n\t"
        "umulh	x4, x6, x8\n\t"
        "adcs	x17, x17, x4\n\t"
        /*  A[1] * A[3] */
        "mul	x3, x7, x9\n\t"
        "adcs	x25, x25, x3\n\t"
        "umulh	x26, x7, x9\n\t"
        "adc	x26, x26, xzr\n\t"
        /*  A[1] * A[2] */
        "mul	x3, x7, x8\n\t"
        "adds	x17, x17, x3\n\t"
        "umulh	x4, x7, x8\n\t"
        "adcs	x25, x25, x4\n\t"
        /*  A[2] * A[3] */
        "mul	x3, x8, x9\n\t"
        "adcs	x26, x26, x3\n\t"
        "umulh	x27, x8, x9\n\t"
        "adc	x27, x27, xzr\n\t"
        /* Double */
        "adds	x15, x15, x15\n\t"
        "adcs	x16, x16, x16\n\t"
        "adcs	x17, x17, x17\n\t"
        "adcs	x25, x25, x25\n\t"
        "adcs	x26, x26, x26\n\t"
        "adcs	x27, x27, x27\n\t"
        "adc	x28, xzr, xzr\n\t"
        /*  A[0] * A[0] */
        "umulh	x4, x6, x6\n\t"
        "mul	x14, x6, x6\n\t"
        /*  A[1] * A[1] */
        "mul	x3, x7, x7\n\t"
        "adds	x15, x15, x4\n\t"
        "umulh	x4, x7, x7\n\t"
        "adcs	x16, x16, x3\n\t"
        /*  A[2] * A[2] */
        "mul	x3, x8, x8\n\t"
        "adcs	x17, x17, x4\n\t"
        "umulh	x4, x8, x8\n\t"
        "adcs	x25, x25, x3\n\t"
        /*  A[3] * A[3] */
        "mul	x3, x9, x9\n\t"
        "adcs	x26, x26, x4\n\t"
        "umulh	x4, x9, x9\n\t"
        "adcs	x27, x27, x3\n\t"
        "adc	x28, x28, x4\n\t"
        /* Reduce */
        "mov	x3, #38\n\t"
        "mul	x4, x3, x28\n\t"
        "adds	x17, x17, x4\n\t"
        "umulh	x5, x3, x28\n\t"
        "adc	x5, x5, xzr\n\t"
        "mov	x3, #19\n\t"
        "extr	x5, x5, x17, #63\n\t"
        "mul	x5, x5, x3\n\t"
        "and	x17, x17, #0x7fffffffffffffff\n\t"
        "mov	x3, #38\n\t"
        "mul	x4, x3, x25\n\t"
        "adds	x14, x14, x4\n\t"
        "umulh	x25, x3, x25\n\t"
        "mul	x4, x3, x26\n\t"
        "adcs	x15, x15, x4\n\t"
        "umulh	x26, x3, x26\n\t"
        "mul	x4, x3, x27\n\t"
        "adcs	x16, x16, x4\n\t"
        "umulh	x27, x3, x27\n\t"
        "adc	x17, x17, xzr\n\t"
        /*  Add high product results in */
        "adds	x14, x14, x5\n\t"
        "adcs	x15, x15, x25\n\t"
        "adcs	x16, x16, x26\n\t"
        "adc	x17, x17, x27\n\t"
        /* Multiply */
        /* A[0] * B[0] */
        "umulh	x7, x14, x10\n\t"
        "mul	x6, x14, x10\n\t"
        /* A[2] * B[0] */
        "umulh	x9, x16, x10\n\t"
        "mul	x8, x16, x10\n\t"
        /* A[1] * B[0] */
        "mul	x3, x15, x10\n\t"
        "adds	x7, x7, x3\n\t"
        "umulh	x4, x15, x10\n\t"
        "adcs	x8, x8, x4\n\t"
        /* A[1] * B[3] */
        "umulh	x26, x15, x13\n\t"
        "adc	x9, x9, xzr\n\t"
        "mul	x25, x15, x13\n\t"
        /* A[0] * B[1] */
        "mul	x3, x14, x11\n\t"
        "adds	x7, x7, x3\n\t"
        "umulh	x4, x14, x11\n\t"
        "adcs	x8, x8, x4\n\t"
        /* A[2] * B[1] */
        "mul	x3, x16, x11\n\t"
        "adcs	x9, x9, x3\n\t"
        "umulh	x4, x16, x11\n\t"
        "adcs	x25, x25, x4\n\t"
        "adc	x26, x26, xzr\n\t"
        /* A[1] * B[2] */
        "mul	x3, x15, x12\n\t"
        "adds	x9, x9, x3\n\t"
        "umulh	x4, x15, x12\n\t"
        "adcs	x25, x25, x4\n\t"
        "adcs	x26, x26, xzr\n\t"
        "adc	x27, xzr, xzr\n\t"
        /* A[0] * B[2] */
        "mul	x3, x14, x12\n\t"
        "adds	x8, x8, x3\n\t"
        "umulh	x4, x14, x12\n\t"
        "adcs	x9, x9, x4\n\t"
        "adcs	x25, x25, xzr\n\t"
        "adcs	x26, x26, xzr\n\t"
        "adc	x27, x27, xzr\n\t"
        /* A[1] * B[1] */
        "mul	x3, x15, x11\n\t"
        "adds	x8, x8, x3\n\t"
        "umulh	x4, x15, x11\n\t"
        "adcs	x9, x9, x4\n\t"
        /* A[3] * B[1] */
        "mul	x3, x17, x11\n\t"
        "adcs	x25, x25, x3\n\t"
        "umulh	x4, x17, x11\n\t"
        "adcs	x26, x26, x4\n\t"
        "adc	x27, x27, xzr\n\t"
        /* A[2] * B[2] */
        "mul	x3, x16, x12\n\t"
        "adds	x25, x25, x3\n\t"
        "umulh	x4, x16, x12\n\t"
        "adcs	x26, x26, x4\n\t"
        /* A[3] * B[3] */
        "mul	x3, x17, x13\n\t"
        "adcs	x27, x27, x3\n\t"
        "umulh	x28, x17, x13\n\t"
        "adc	x28, x28, xzr\n\t"
        /* A[0] * B[3] */
        "mul	x3, x14, x13\n\t"
        "adds	x9, x9, x3\n\t"
        "umulh	x4, x14, x13\n\t"
        "adcs	x25, x25, x4\n\t"
        /* A[2] * B[3] */
        "mul	x3, x16, x13\n\t"
        "adcs	x26, x26, x3\n\t"
        "umulh	x4, x16, x13\n\t"
        "adcs	x27, x27, x4\n\t"
        "adc	x28, x28, xzr\n\t"
        /* A[3] * B[0] */
        "mul	x3, x17, x10\n\t"
        "adds	x9, x9, x3\n\t"
        "umulh	x4, x17, x10\n\t"
        "adcs	x25, x25, x4\n\t"
        /* A[3] * B[2] */
        "mul	x3, x17, x12\n\t"
        "adcs	x26, x26, x3\n\t"
        "umulh	x4, x17, x12\n\t"
        "adcs	x27, x27, x4\n\t"
        "adc	x28, x28, xzr\n\t"
        /* Reduce */
        "mov	x3, #38\n\t"
        "mul	x4, x3, x28\n\t"
        "adds	x9, x9, x4\n\t"
        "umulh	x5, x3, x28\n\t"
        "adc	x5, x5, xzr\n\t"
        "mov	x3, #19\n\t"
        "extr	x5, x5, x9, #63\n\t"
        "mul	x5, x5, x3\n\t"
        "and	x9, x9, #0x7fffffffffffffff\n\t"
        "mov	x3, #38\n\t"
        "mul	x4, x3, x25\n\t"
        "adds	x6, x6, x4\n\t"
        "umulh	x25, x3, x25\n\t"
        "mul	x4, x3, x26\n\t"
        "adcs	x7, x7, x4\n\t"
        "umulh	x26, x3, x26\n\t"
        "mul	x4, x3, x27\n\t"
        "adcs	x8, x8, x4\n\t"
        "umulh	x27, x3, x27\n\t"
        "adc	x9, x9, xzr\n\t"
        /*  Add high product results in */
        "adds	x6, x6, x5\n\t"
        "adcs	x7, x7, x25\n\t"
        "adcs	x8, x8, x26\n\t"
        "adc	x9, x9, x27\n\t"
        /* Store */
        "stp	x6, x7, [%x[r]]\n\t"
        "stp	x8, x9, [%x[r], #16]\n\t"
        /* Sub */
        "subs	x14, x14, x10\n\t"
        "sbcs	x15, x15, x11\n\t"
        "sbcs	x16, x16, x12\n\t"
        "sbcs	x17, x17, x13\n\t"
        "csetm	x5, cc\n\t"
        "mov	x3, #-19\n\t"
        /*   Mask the modulus */
        "extr	x5, x5, x17, #63\n\t"
        "mul	x3, x5, x3\n\t"
        /*   Add modulus (if underflow) */
        "subs	x14, x14, x3\n\t"
        "sbcs	x15, x15, xzr\n\t"
        "and	x17, x17, #0x7fffffffffffffff\n\t"
        "sbcs	x16, x16, xzr\n\t"
        "sbc	x17, x17, xzr\n\t"
        /* Multiply by 121666 */
        "mov	x5, #0xdb42\n\t"
        "movk	x5, #1, lsl 16\n\t"
        "mul	x6, x14, x5\n\t"
        "umulh	x7, x14, x5\n\t"
        "mul	x3, x15, x5\n\t"
        "umulh	x8, x15, x5\n\t"
        "adds	x7, x7, x3\n\t"
        "adc	x8, x8, xzr\n\t"
        "mul	x3, x16, x5\n\t"
        "umulh	x9, x16, x5\n\t"
        "adds	x8, x8, x3\n\t"
        "adc	x9, x9, xzr\n\t"
        "mul	x3, x17, x5\n\t"
        "umulh	x4, x17, x5\n\t"
        "adds	x9, x9, x3\n\t"
        "adc	x4, x4, xzr\n\t"
        "mov	x5, #19\n\t"
        "extr	x4, x4, x9, #63\n\t"
        "mul	x4, x4, x5\n\t"
        "adds	x6, x6, x4\n\t"
        "adcs	x7, x7, xzr\n\t"
        "and	x9, x9, #0x7fffffffffffffff\n\t"
        "adcs	x8, x8, xzr\n\t"
        "adc	x9, x9, xzr\n\t"
        /* Add */
        "adds	x10, x10, x6\n\t"
        "adcs	x11, x11, x7\n\t"
        "adcs	x12, x12, x8\n\t"
        "adcs	x13, x13, x9\n\t"
        "cset	x5, cs\n\t"
        "mov	x3, #19\n\t"
        /*   Mask the modulus */
        "extr	x5, x5, x13, #63\n\t"
        "mul	x3, x5, x3\n\t"
        /*   Sub modulus (if overflow) */
        "adds	x10, x10, x3\n\t"
        "adcs	x11, x11, xzr\n\t"
        "and	x13, x13, #0x7fffffffffffffff\n\t"
        "adcs	x12, x12, xzr\n\t"
        "adc	x13, x13, xzr\n\t"
        /* Multiply */
        /* A[0] * B[0] */
        "umulh	x7, x14, x10\n\t"
        "mul	x6, x14, x10\n\t"
        /* A[2] * B[0] */
        "umulh	x9, x16, x10\n\t"
        "mul	x8, x16, x10\n\t"
        /* A[1] * B[0] */
        "mul	x3, x15, x10\n\t"
        "adds	x7, x7, x3\n\t"
        "umulh	x4, x15, x10\n\t"
        "adcs	x8, x8, x4\n\t"
        /* A[1] * B[3] */
        "umulh	x26, x15, x13\n\t"
        "adc	x9, x9, xzr\n\t"
        "mul	x25, x15, x13\n\t"
        /* A[0] * B[1] */
        "mul	x3, x14, x11\n\t"
        "adds	x7, x7, x3\n\t"
        "umulh	x4, x14, x11\n\t"
        "adcs	x8, x8, x4\n\t"
        /* A[2] * B[1] */
        "mul	x3, x16, x11\n\t"
        "adcs	x9, x9, x3\n\t"
        "umulh	x4, x16, x11\n\t"
        "adcs	x25, x25, x4\n\t"
        "adc	x26, x26, xzr\n\t"
        /* A[1] * B[2] */
        "mul	x3, x15, x12\n\t"
        "adds	x9, x9, x3\n\t"
        "umulh	x4, x15, x12\n\t"
        "adcs	x25, x25, x4\n\t"
        "adcs	x26, x26, xzr\n\t"
        "adc	x27, xzr, xzr\n\t"
        /* A[0] * B[2] */
        "mul	x3, x14, x12\n\t"
        "adds	x8, x8, x3\n\t"
        "umulh	x4, x14, x12\n\t"
        "adcs	x9, x9, x4\n\t"
        "adcs	x25, x25, xzr\n\t"
        "adcs	x26, x26, xzr\n\t"
        "adc	x27, x27, xzr\n\t"
        /* A[1] * B[1] */
        "mul	x3, x15, x11\n\t"
        "adds	x8, x8, x3\n\t"
        "umulh	x4, x15, x11\n\t"
        "adcs	x9, x9, x4\n\t"
        /* A[3] * B[1] */
        "mul	x3, x17, x11\n\t"
        "adcs	x25, x25, x3\n\t"
        "umulh	x4, x17, x11\n\t"
        "adcs	x26, x26, x4\n\t"
        "adc	x27, x27, xzr\n\t"
        /* A[2] * B[2] */
        "mul	x3, x16, x12\n\t"
        "adds	x25, x25, x3\n\t"
        "umulh	x4, x16, x12\n\t"
        "adcs	x26, x26, x4\n\t"
        /* A[3] * B[3] */
        "mul	x3, x17, x13\n\t"
        "adcs	x27, x27, x3\n\t"
        "umulh	x28, x17, x13\n\t"
        "adc	x28, x28, xzr\n\t"
        /* A[0] * B[3] */
        "mul	x3, x14, x13\n\t"
        "adds	x9, x9, x3\n\t"
        "umulh	x4, x14, x13\n\t"
        "adcs	x25, x25, x4\n\t"
        /* A[2] * B[3] */
        "mul	x3, x16, x13\n\t"
        "adcs	x26, x26, x3\n\t"
        "umulh	x4, x16, x13\n\t"
        "adcs	x27, x27, x4\n\t"
        "adc	x28, x28, xzr\n\t"
        /* A[3] * B[0] */
        "mul	x3, x17, x10\n\t"
        "adds	x9, x9, x3\n\t"
        "umulh	x4, x17, x10\n\t"
        "adcs	x25, x25, x4\n\t"
        /* A[3] * B[2] */
        "mul	x3, x17, x12\n\t"
        "adcs	x26, x26, x3\n\t"
        "umulh	x4, x17, x12\n\t"
        "adcs	x27, x27, x4\n\t"
        "adc	x28, x28, xzr\n\t"
        /* Reduce */
        "mov	x3, #38\n\t"
        "mul	x4, x3, x28\n\t"
        "adds	x9, x9, x4\n\t"
        "umulh	x5, x3, x28\n\t"
        "adc	x5, x5, xzr\n\t"
        "mov	x3, #19\n\t"
        "extr	x5, x5, x9, #63\n\t"
        "mul	x5, x5, x3\n\t"
        "and	x9, x9, #0x7fffffffffffffff\n\t"
        "mov	x3, #38\n\t"
        "mul	x4, x3, x25\n\t"
        "adds	x6, x6, x4\n\t"
        "umulh	x25, x3, x25\n\t"
        "mul	x4, x3, x26\n\t"
        "adcs	x7, x7, x4\n\t"
        "umulh	x26, x3, x26\n\t"
        "mul	x4, x3, x27\n\t"
        "adcs	x8, x8, x4\n\t"
        "umulh	x27, x3, x27\n\t"
        "adc	x9, x9, xzr\n\t"
        /*  Add high product results in */
        "adds	x6, x6, x5\n\t"
        "adcs	x7, x7, x25\n\t"
        "adcs	x8, x8, x26\n\t"
        "adc	x9, x9, x27\n\t"
        /* Store */
        "stp	x6, x7, [x29, #16]\n\t"
        "stp	x8, x9, [x29, #32]\n\t"
        /* Add */
        "ldp	x25, x26, [x29, #48]\n\t"
        "ldp	x27, x28, [x29, #64]\n\t"
        "adds	x10, x25, x19\n\t"
        "adcs	x11, x26, x20\n\t"
        "adcs	x12, x27, x21\n\t"
        "adcs	x13, x28, x22\n\t"
        "cset	x5, cs\n\t"
        "mov	x3, #19\n\t"
        "extr	x5, x5, x13, #63\n\t"
        "mul	x3, x5, x3\n\t"
        /*   Sub modulus (if overflow) */
        "adds	x10, x10, x3\n\t"
        "adcs	x11, x11, xzr\n\t"
        "and	x13, x13, #0x7fffffffffffffff\n\t"
        "adcs	x12, x12, xzr\n\t"
        "adc	x13, x13, xzr\n\t"
        /* Sub */
        "subs	x19, x25, x19\n\t"
        "sbcs	x20, x26, x20\n\t"
        "sbcs	x21, x27, x21\n\t"
        "sbcs	x22, x28, x22\n\t"
        "csetm	x5, cc\n\t"
        "mov	x3, #-19\n\t"
        "extr	x5, x5, x22, #63\n\t"
        "mul	x3, x5, x3\n\t"
        /*   Add modulus (if underflow) */
        "subs	x19, x19, x3\n\t"
        "sbcs	x20, x20, xzr\n\t"
        "and	x22, x22, #0x7fffffffffffffff\n\t"
        "sbcs	x21, x21, xzr\n\t"
        "sbc	x22, x22, xzr\n\t"
        /* Square */
        /*  A[0] * A[1] */
        "umulh	x8, x10, x11\n\t"
        "mul	x7, x10, x11\n\t"
        /*  A[0] * A[3] */
        "umulh	x25, x10, x13\n\t"
        "mul	x9, x10, x13\n\t"
        /*  A[0] * A[2] */
        "mul	x3, x10, x12\n\t"
        "adds	x8, x8, x3\n\t"
        "umulh	x4, x10, x12\n\t"
        "adcs	x9, x9, x4\n\t"
        /*  A[1] * A[3] */
        "mul	x3, x11, x13\n\t"
        "adcs	x25, x25, x3\n\t"
        "umulh	x26, x11, x13\n\t"
        "adc	x26, x26, xzr\n\t"
        /*  A[1] * A[2] */
        "mul	x3, x11, x12\n\t"
        "adds	x9, x9, x3\n\t"
        "umulh	x4, x11, x12\n\t"
        "adcs	x25, x25, x4\n\t"
        /*  A[2] * A[3] */
        "mul	x3, x12, x13\n\t"
        "adcs	x26, x26, x3\n\t"
        "umulh	x27, x12, x13\n\t"
        "adc	x27, x27, xzr\n\t"
        /* Double */
        "adds	x7, x7, x7\n\t"
        "adcs	x8, x8, x8\n\t"
        "adcs	x9, x9, x9\n\t"
        "adcs	x25, x25, x25\n\t"
        "adcs	x26, x26, x26\n\t"
        "adcs	x27, x27, x27\n\t"
        "adc	x28, xzr, xzr\n\t"
        /*  A[0] * A[0] */
        "umulh	x4, x10, x10\n\t"
        "mul	x6, x10, x10\n\t"
        /*  A[1] * A[1] */
        "mul	x3, x11, x11\n\t"
        "adds	x7, x7, x4\n\t"
        "umulh	x4, x11, x11\n\t"
        "adcs	x8, x8, x3\n\t"
        /*  A[2] * A[2] */
        "mul	x3, x12, x12\n\t"
        "adcs	x9, x9, x4\n\t"
        "umulh	x4, x12, x12\n\t"
        "adcs	x25, x25, x3\n\t"
        /*  A[3] * A[3] */
        "mul	x3, x13, x13\n\t"
        "adcs	x26, x26, x4\n\t"
        "umulh	x4, x13, x13\n\t"
        "adcs	x27, x27, x3\n\t"
        "adc	x28, x28, x4\n\t"
        /* Reduce */
        "mov	x3, #38\n\t"
        "mul	x4, x3, x28\n\t"
        "adds	x9, x9, x4\n\t"
        "umulh	x5, x3, x28\n\t"
        "adc	x5, x5, xzr\n\t"
        "mov	x3, #19\n\t"
        "extr	x5, x5, x9, #63\n\t"
        "mul	x5, x5, x3\n\t"
        "and	x9, x9, #0x7fffffffffffffff\n\t"
        "mov	x3, #38\n\t"
        "mul	x4, x3, x25\n\t"
        "adds	x6, x6, x4\n\t"
        "umulh	x25, x3, x25\n\t"
        "mul	x4, x3, x26\n\t"
        "adcs	x7, x7, x4\n\t"
        "umulh	x26, x3, x26\n\t"
        "mul	x4, x3, x27\n\t"
        "adcs	x8, x8, x4\n\t"
        "umulh	x27, x3, x27\n\t"
        "adc	x9, x9, xzr\n\t"
        /*  Add high product results in */
        "adds	x6, x6, x5\n\t"
        "adcs	x7, x7, x25\n\t"
        "adcs	x8, x8, x26\n\t"
        "adc	x9, x9, x27\n\t"
        /* Square */
        /*  A[0] * A[1] */
        "umulh	x16, x19, x20\n\t"
        "mul	x15, x19, x20\n\t"
        /*  A[0] * A[3] */
        "umulh	x25, x19, x22\n\t"
        "mul	x17, x19, x22\n\t"
        /*  A[0] * A[2] */
        "mul	x3, x19, x21\n\t"
        "adds	x16, x16, x3\n\t"
        "umulh	x4, x19, x21\n\t"
        "adcs	x17, x17, x4\n\t"
        /*  A[1] * A[3] */
        "mul	x3, x20, x22\n\t"
        "adcs	x25, x25, x3\n\t"
        "umulh	x26, x20, x22\n\t"
        "adc	x26, x26, xzr\n\t"
        /*  A[1] * A[2] */
        "mul	x3, x20, x21\n\t"
        "adds	x17, x17, x3\n\t"
        "umulh	x4, x20, x21\n\t"
        "adcs	x25, x25, x4\n\t"
        /*  A[2] * A[3] */
        "mul	x3, x21, x22\n\t"
        "adcs	x26, x26, x3\n\t"
        "umulh	x27, x21, x22\n\t"
        "adc	x27, x27, xzr\n\t"
        /* Double */
        "adds	x15, x15, x15\n\t"
        "adcs	x16, x16, x16\n\t"
        "adcs	x17, x17, x17\n\t"
        "adcs	x25, x25, x25\n\t"
        "adcs	x26, x26, x26\n\t"
        "adcs	x27, x27, x27\n\t"
        "adc	x28, xzr, xzr\n\t"
        /*  A[0] * A[0] */
        "umulh	x4, x19, x19\n\t"
        "mul	x14, x19, x19\n\t"
        /*  A[1] * A[1] */
        "mul	x3, x20, x20\n\t"
        "adds	x15, x15, x4\n\t"
        "umulh	x4, x20, x20\n\t"
        "adcs	x16, x16, x3\n\t"
        /*  A[2] * A[2] */
        "mul	x3, x21, x21\n\t"
        "adcs	x17, x17, x4\n\t"
        "umulh	x4, x21, x21\n\t"
        "adcs	x25, x25, x3\n\t"
        /*  A[3] * A[3] */
        "mul	x3, x22, x22\n\t"
        "adcs	x26, x26, x4\n\t"
        "umulh	x4, x22, x22\n\t"
        "adcs	x27, x27, x3\n\t"
        "adc	x28, x28, x4\n\t"
        /* Reduce */
        "mov	x3, #38\n\t"
        "mul	x4, x3, x28\n\t"
        "adds	x17, x17, x4\n\t"
        "umulh	x5, x3, x28\n\t"
        "adc	x5, x5, xzr\n\t"
        "mov	x3, #19\n\t"
        "extr	x5, x5, x17, #63\n\t"
        "mul	x5, x5, x3\n\t"
        "and	x17, x17, #0x7fffffffffffffff\n\t"
        "mov	x3, #38\n\t"
        "mul	x4, x3, x25\n\t"
        "adds	x14, x14, x4\n\t"
        "umulh	x25, x3, x25\n\t"
        "mul	x4, x3, x26\n\t"
        "adcs	x15, x15, x4\n\t"
        "umulh	x26, x3, x26\n\t"
        "mul	x4, x3, x27\n\t"
        "adcs	x16, x16, x4\n\t"
        "umulh	x27, x3, x27\n\t"
        "adc	x17, x17, xzr\n\t"
        /*  Add high product results in */
        "adds	x14, x14, x5\n\t"
        "adcs	x15, x15, x25\n\t"
        "adcs	x16, x16, x26\n\t"
        "adc	x17, x17, x27\n\t"
        /* Multiply */
        "ldp	x19, x20, [%x[a]]\n\t"
        "ldp	x21, x22, [%x[a], #16]\n\t"
        /* A[0] * B[0] */
        "umulh	x11, x19, x14\n\t"
        "mul	x10, x19, x14\n\t"
        /* A[2] * B[0] */
        "umulh	x13, x21, x14\n\t"
        "mul	x12, x21, x14\n\t"
        /* A[1] * B[0] */
        "mul	x3, x20, x14\n\t"
        "adds	x11, x11, x3\n\t"
        "umulh	x4, x20, x14\n\t"
        "adcs	x12, x12, x4\n\t"
        /* A[1] * B[3] */
        "umulh	x26, x20, x17\n\t"
        "adc	x13, x13, xzr\n\t"
        "mul	x25, x20, x17\n\t"
        /* A[0] * B[1] */
        "mul	x3, x19, x15\n\t"
        "adds	x11, x11, x3\n\t"
        "umulh	x4, x19, x15\n\t"
        "adcs	x12, x12, x4\n\t"
        /* A[2] * B[1] */
        "mul	x3, x21, x15\n\t"
        "adcs	x13, x13, x3\n\t"
        "umulh	x4, x21, x15\n\t"
        "adcs	x25, x25, x4\n\t"
        "adc	x26, x26, xzr\n\t"
        /* A[1] * B[2] */
        "mul	x3, x20, x16\n\t"
        "adds	x13, x13, x3\n\t"
        "umulh	x4, x20, x16\n\t"
        "adcs	x25, x25, x4\n\t"
        "adcs	x26, x26, xzr\n\t"
        "adc	x27, xzr, xzr\n\t"
        /* A[0] * B[2] */
        "mul	x3, x19, x16\n\t"
        "adds	x12, x12, x3\n\t"
        "umulh	x4, x19, x16\n\t"
        "adcs	x13, x13, x4\n\t"
        "adcs	x25, x25, xzr\n\t"
        "adcs	x26, x26, xzr\n\t"
        "adc	x27, x27, xzr\n\t"
        /* A[1] * B[1] */
        "mul	x3, x20, x15\n\t"
        "adds	x12, x12, x3\n\t"
        "umulh	x4, x20, x15\n\t"
        "adcs	x13, x13, x4\n\t"
        /* A[3] * B[1] */
        "mul	x3, x22, x15\n\t"
        "adcs	x25, x25, x3\n\t"
        "umulh	x4, x22, x15\n\t"
        "adcs	x26, x26, x4\n\t"
        "adc	x27, x27, xzr\n\t"
        /* A[2] * B[2] */
        "mul	x3, x21, x16\n\t"
        "adds	x25, x25, x3\n\t"
        "umulh	x4, x21, x16\n\t"
        "adcs	x26, x26, x4\n\t"
        /* A[3] * B[3] */
        "mul	x3, x22, x17\n\t"
        "adcs	x27, x27, x3\n\t"
        "umulh	x28, x22, x17\n\t"
        "adc	x28, x28, xzr\n\t"
        /* A[0] * B[3] */
        "mul	x3, x19, x17\n\t"
        "adds	x13, x13, x3\n\t"
        "umulh	x4, x19, x17\n\t"
        "adcs	x25, x25, x4\n\t"
        /* A[2] * B[3] */
        "mul	x3, x21, x17\n\t"
        "adcs	x26, x26, x3\n\t"
        "umulh	x4, x21, x17\n\t"
        "adcs	x27, x27, x4\n\t"
        "adc	x28, x28, xzr\n\t"
        /* A[3] * B[0] */
        "mul	x3, x22, x14\n\t"
        "adds	x13, x13, x3\n\t"
        "umulh	x4, x22, x14\n\t"
        "adcs	x25, x25, x4\n\t"
        /* A[3] * B[2] */
        "mul	x3, x22, x16\n\t"
        "adcs	x26, x26, x3\n\t"
        "umulh	x4, x22, x16\n\t"
        "adcs	x27, x27, x4\n\t"
        "adc	x28, x28, xzr\n\t"
        /* Reduce */
        "mov	x3, #38\n\t"
        "mul	x4, x3, x28\n\t"
        "adds	x13, x13, x4\n\t"
        "umulh	x5, x3, x28\n\t"
        "adc	x5, x5, xzr\n\t"
        "mov	x3, #19\n\t"
        "extr	x5, x5, x13, #63\n\t"
        "mul	x5, x5, x3\n\t"
        "and	x13, x13, #0x7fffffffffffffff\n\t"
        "mov	x3, #38\n\t"
        "mul	x4, x3, x25\n\t"
        "adds	x10, x10, x4\n\t"
        "umulh	x25, x3, x25\n\t"
        "mul	x4, x3, x26\n\t"
        "adcs	x11, x11, x4\n\t"
        "umulh	x26, x3, x26\n\t"
        "mul	x4, x3, x27\n\t"
        "adcs	x12, x12, x4\n\t"
        "umulh	x27, x3, x27\n\t"
        "adc	x13, x13, xzr\n\t"
        /*  Add high product results in */
        "adds	x10, x10, x5\n\t"
        "adcs	x11, x11, x25\n\t"
        "adcs	x12, x12, x26\n\t"
        "adc	x13, x13, x27\n\t"
        "subs	x24, x24, #1\n\t"
        "b.ge	L_curve25519_bits_%=\n\t"
        /* Invert */
        "add	x0, x29, #48\n\t"
        "add	x1, x29, #16\n\t"
#ifndef __APPLE__
        "bl	fe_sq\n\t"
#else
        "bl	_fe_sq\n\t"
#endif /* __APPLE__ */
        "add	x0, x29, #0x50\n\t"
        "add	x1, x29, #48\n\t"
#ifndef __APPLE__
        "bl	fe_sq\n\t"
#else
        "bl	_fe_sq\n\t"
#endif /* __APPLE__ */
#ifndef NDEBUG
        "add	x0, x29, #0x50\n\t"
#endif /* !NDEBUG */
        "add	x1, x29, #0x50\n\t"
#ifndef __APPLE__
        "bl	fe_sq\n\t"
#else
        "bl	_fe_sq\n\t"
#endif /* __APPLE__ */
#ifndef NDEBUG
        "add	x0, x29, #0x50\n\t"
#endif /* !NDEBUG */
        "add	x1, x29, #16\n\t"
        "add	x2, x29, #0x50\n\t"
#ifndef __APPLE__
        "bl	fe_mul\n\t"
#else
        "bl	_fe_mul\n\t"
#endif /* __APPLE__ */
        "add	x0, x29, #48\n\t"
        "add	x1, x29, #48\n\t"
        "add	x2, x29, #0x50\n\t"
#ifndef __APPLE__
        "bl	fe_mul\n\t"
#else
        "bl	_fe_mul\n\t"
#endif /* __APPLE__ */
        "add	x0, x29, #0x70\n\t"
#ifndef NDEBUG
        "add	x1, x29, #48\n\t"
#endif /* !NDEBUG */
#ifndef __APPLE__
        "bl	fe_sq\n\t"
#else
        "bl	_fe_sq\n\t"
#endif /* __APPLE__ */
        "add	x0, x29, #0x50\n\t"
        "add	x1, x29, #0x50\n\t"
        "add	x2, x29, #0x70\n\t"
#ifndef __APPLE__
        "bl	fe_mul\n\t"
#else
        "bl	_fe_mul\n\t"
#endif /* __APPLE__ */
        /* Loop: 5 times */
        "mov	x24, #5\n\t"
        "ldp	x6, x7, [x29, #80]\n\t"
        "ldp	x8, x9, [x29, #96]\n\t"
        "\n"
    "L_curve25519_inv_1_%=: \n\t"
        /* Square */
        /*  A[0] * A[1] */
        "umulh	x12, x6, x7\n\t"
        "mul	x11, x6, x7\n\t"
        /*  A[0] * A[3] */
        "umulh	x14, x6, x9\n\t"
        "mul	x13, x6, x9\n\t"
        /*  A[0] * A[2] */
        "mul	x3, x6, x8\n\t"
        "adds	x12, x12, x3\n\t"
        "umulh	x4, x6, x8\n\t"
        "adcs	x13, x13, x4\n\t"
        /*  A[1] * A[3] */
        "mul	x3, x7, x9\n\t"
        "adcs	x14, x14, x3\n\t"
        "umulh	x15, x7, x9\n\t"
        "adc	x15, x15, xzr\n\t"
        /*  A[1] * A[2] */
        "mul	x3, x7, x8\n\t"
        "adds	x13, x13, x3\n\t"
        "umulh	x4, x7, x8\n\t"
        "adcs	x14, x14, x4\n\t"
        /*  A[2] * A[3] */
        "mul	x3, x8, x9\n\t"
        "adcs	x15, x15, x3\n\t"
        "umulh	x16, x8, x9\n\t"
        "adc	x16, x16, xzr\n\t"
        /* Double */
        "adds	x11, x11, x11\n\t"
        "adcs	x12, x12, x12\n\t"
        "adcs	x13, x13, x13\n\t"
        "adcs	x14, x14, x14\n\t"
        "adcs	x15, x15, x15\n\t"
        "adcs	x16, x16, x16\n\t"
        "adc	x17, xzr, xzr\n\t"
        /*  A[0] * A[0] */
        "umulh	x4, x6, x6\n\t"
        "mul	x10, x6, x6\n\t"
        /*  A[1] * A[1] */
        "mul	x3, x7, x7\n\t"
        "adds	x11, x11, x4\n\t"
        "umulh	x4, x7, x7\n\t"
        "adcs	x12, x12, x3\n\t"
        /*  A[2] * A[2] */
        "mul	x3, x8, x8\n\t"
        "adcs	x13, x13, x4\n\t"
        "umulh	x4, x8, x8\n\t"
        "adcs	x14, x14, x3\n\t"
        /*  A[3] * A[3] */
        "mul	x3, x9, x9\n\t"
        "adcs	x15, x15, x4\n\t"
        "umulh	x4, x9, x9\n\t"
        "adcs	x16, x16, x3\n\t"
        "adc	x17, x17, x4\n\t"
        /* Reduce */
        "mov	x3, #38\n\t"
        "mul	x4, x3, x17\n\t"
        "adds	x13, x13, x4\n\t"
        "umulh	x5, x3, x17\n\t"
        "adc	x5, x5, xzr\n\t"
        "mov	x3, #19\n\t"
        "extr	x5, x5, x13, #63\n\t"
        "mul	x5, x5, x3\n\t"
        "and	x13, x13, #0x7fffffffffffffff\n\t"
        "mov	x3, #38\n\t"
        "mul	x4, x3, x14\n\t"
        "adds	x10, x10, x4\n\t"
        "umulh	x14, x3, x14\n\t"
        "mul	x4, x3, x15\n\t"
        "adcs	x11, x11, x4\n\t"
        "umulh	x15, x3, x15\n\t"
        "mul	x4, x3, x16\n\t"
        "adcs	x12, x12, x4\n\t"
        "umulh	x16, x3, x16\n\t"
        "adc	x13, x13, xzr\n\t"
        /*  Add high product results in */
        "adds	x6, x10, x5\n\t"
        "adcs	x7, x11, x14\n\t"
        "adcs	x8, x12, x15\n\t"
        "adc	x9, x13, x16\n\t"
        "subs	x24, x24, #1\n\t"
        "b.ne	L_curve25519_inv_1_%=\n\t"
        /* Store */
        "stp	x6, x7, [x29, #112]\n\t"
        "stp	x8, x9, [x29, #128]\n\t"
#ifndef NDEBUG
        "add	x0, x29, #0x50\n\t"
#endif /* !NDEBUG */
        "add	x1, x29, #0x70\n\t"
        "add	x2, x29, #0x50\n\t"
#ifndef __APPLE__
        "bl	fe_mul\n\t"
#else
        "bl	_fe_mul\n\t"
#endif /* __APPLE__ */
        /* Loop: 10 times */
        "mov	x24, #10\n\t"
        "ldp	x6, x7, [x29, #80]\n\t"
        "ldp	x8, x9, [x29, #96]\n\t"
        "\n"
    "L_curve25519_inv_2_%=: \n\t"
        /* Square */
        /*  A[0] * A[1] */
        "umulh	x12, x6, x7\n\t"
        "mul	x11, x6, x7\n\t"
        /*  A[0] * A[3] */
        "umulh	x14, x6, x9\n\t"
        "mul	x13, x6, x9\n\t"
        /*  A[0] * A[2] */
        "mul	x3, x6, x8\n\t"
        "adds	x12, x12, x3\n\t"
        "umulh	x4, x6, x8\n\t"
        "adcs	x13, x13, x4\n\t"
        /*  A[1] * A[3] */
        "mul	x3, x7, x9\n\t"
        "adcs	x14, x14, x3\n\t"
        "umulh	x15, x7, x9\n\t"
        "adc	x15, x15, xzr\n\t"
        /*  A[1] * A[2] */
        "mul	x3, x7, x8\n\t"
        "adds	x13, x13, x3\n\t"
        "umulh	x4, x7, x8\n\t"
        "adcs	x14, x14, x4\n\t"
        /*  A[2] * A[3] */
        "mul	x3, x8, x9\n\t"
        "adcs	x15, x15, x3\n\t"
        "umulh	x16, x8, x9\n\t"
        "adc	x16, x16, xzr\n\t"
        /* Double */
        "adds	x11, x11, x11\n\t"
        "adcs	x12, x12, x12\n\t"
        "adcs	x13, x13, x13\n\t"
        "adcs	x14, x14, x14\n\t"
        "adcs	x15, x15, x15\n\t"
        "adcs	x16, x16, x16\n\t"
        "adc	x17, xzr, xzr\n\t"
        /*  A[0] * A[0] */
        "umulh	x4, x6, x6\n\t"
        "mul	x10, x6, x6\n\t"
        /*  A[1] * A[1] */
        "mul	x3, x7, x7\n\t"
        "adds	x11, x11, x4\n\t"
        "umulh	x4, x7, x7\n\t"
        "adcs	x12, x12, x3\n\t"
        /*  A[2] * A[2] */
        "mul	x3, x8, x8\n\t"
        "adcs	x13, x13, x4\n\t"
        "umulh	x4, x8, x8\n\t"
        "adcs	x14, x14, x3\n\t"
        /*  A[3] * A[3] */
        "mul	x3, x9, x9\n\t"
        "adcs	x15, x15, x4\n\t"
        "umulh	x4, x9, x9\n\t"
        "adcs	x16, x16, x3\n\t"
        "adc	x17, x17, x4\n\t"
        /* Reduce */
        "mov	x3, #38\n\t"
        "mul	x4, x3, x17\n\t"
        "adds	x13, x13, x4\n\t"
        "umulh	x5, x3, x17\n\t"
        "adc	x5, x5, xzr\n\t"
        "mov	x3, #19\n\t"
        "extr	x5, x5, x13, #63\n\t"
        "mul	x5, x5, x3\n\t"
        "and	x13, x13, #0x7fffffffffffffff\n\t"
        "mov	x3, #38\n\t"
        "mul	x4, x3, x14\n\t"
        "adds	x10, x10, x4\n\t"
        "umulh	x14, x3, x14\n\t"
        "mul	x4, x3, x15\n\t"
        "adcs	x11, x11, x4\n\t"
        "umulh	x15, x3, x15\n\t"
        "mul	x4, x3, x16\n\t"
        "adcs	x12, x12, x4\n\t"
        "umulh	x16, x3, x16\n\t"
        "adc	x13, x13, xzr\n\t"
        /*  Add high product results in */
        "adds	x6, x10, x5\n\t"
        "adcs	x7, x11, x14\n\t"
        "adcs	x8, x12, x15\n\t"
        "adc	x9, x13, x16\n\t"
        "subs	x24, x24, #1\n\t"
        "b.ne	L_curve25519_inv_2_%=\n\t"
        /* Store */
        "stp	x6, x7, [x29, #112]\n\t"
        "stp	x8, x9, [x29, #128]\n\t"
        "add	x0, x29, #0x70\n\t"
#ifndef NDEBUG
        "add	x1, x29, #0x70\n\t"
#endif /* !NDEBUG */
        "add	x2, x29, #0x50\n\t"
#ifndef __APPLE__
        "bl	fe_mul\n\t"
#else
        "bl	_fe_mul\n\t"
#endif /* __APPLE__ */
        /* Loop: 20 times */
        "mov	x24, #20\n\t"
        "ldp	x6, x7, [x29, #112]\n\t"
        "ldp	x8, x9, [x29, #128]\n\t"
        "\n"
    "L_curve25519_inv_3_%=: \n\t"
        /* Square */
        /*  A[0] * A[1] */
        "umulh	x12, x6, x7\n\t"
        "mul	x11, x6, x7\n\t"
        /*  A[0] * A[3] */
        "umulh	x14, x6, x9\n\t"
        "mul	x13, x6, x9\n\t"
        /*  A[0] * A[2] */
        "mul	x3, x6, x8\n\t"
        "adds	x12, x12, x3\n\t"
        "umulh	x4, x6, x8\n\t"
        "adcs	x13, x13, x4\n\t"
        /*  A[1] * A[3] */
        "mul	x3, x7, x9\n\t"
        "adcs	x14, x14, x3\n\t"
        "umulh	x15, x7, x9\n\t"
        "adc	x15, x15, xzr\n\t"
        /*  A[1] * A[2] */
        "mul	x3, x7, x8\n\t"
        "adds	x13, x13, x3\n\t"
        "umulh	x4, x7, x8\n\t"
        "adcs	x14, x14, x4\n\t"
        /*  A[2] * A[3] */
        "mul	x3, x8, x9\n\t"
        "adcs	x15, x15, x3\n\t"
        "umulh	x16, x8, x9\n\t"
        "adc	x16, x16, xzr\n\t"
        /* Double */
        "adds	x11, x11, x11\n\t"
        "adcs	x12, x12, x12\n\t"
        "adcs	x13, x13, x13\n\t"
        "adcs	x14, x14, x14\n\t"
        "adcs	x15, x15, x15\n\t"
        "adcs	x16, x16, x16\n\t"
        "adc	x17, xzr, xzr\n\t"
        /*  A[0] * A[0] */
        "umulh	x4, x6, x6\n\t"
        "mul	x10, x6, x6\n\t"
        /*  A[1] * A[1] */
        "mul	x3, x7, x7\n\t"
        "adds	x11, x11, x4\n\t"
        "umulh	x4, x7, x7\n\t"
        "adcs	x12, x12, x3\n\t"
        /*  A[2] * A[2] */
        "mul	x3, x8, x8\n\t"
        "adcs	x13, x13, x4\n\t"
        "umulh	x4, x8, x8\n\t"
        "adcs	x14, x14, x3\n\t"
        /*  A[3] * A[3] */
        "mul	x3, x9, x9\n\t"
        "adcs	x15, x15, x4\n\t"
        "umulh	x4, x9, x9\n\t"
        "adcs	x16, x16, x3\n\t"
        "adc	x17, x17, x4\n\t"
        /* Reduce */
        "mov	x3, #38\n\t"
        "mul	x4, x3, x17\n\t"
        "adds	x13, x13, x4\n\t"
        "umulh	x5, x3, x17\n\t"
        "adc	x5, x5, xzr\n\t"
        "mov	x3, #19\n\t"
        "extr	x5, x5, x13, #63\n\t"
        "mul	x5, x5, x3\n\t"
        "and	x13, x13, #0x7fffffffffffffff\n\t"
        "mov	x3, #38\n\t"
        "mul	x4, x3, x14\n\t"
        "adds	x10, x10, x4\n\t"
        "umulh	x14, x3, x14\n\t"
        "mul	x4, x3, x15\n\t"
        "adcs	x11, x11, x4\n\t"
        "umulh	x15, x3, x15\n\t"
        "mul	x4, x3, x16\n\t"
        "adcs	x12, x12, x4\n\t"
        "umulh	x16, x3, x16\n\t"
        "adc	x13, x13, xzr\n\t"
        /*  Add high product results in */
        "adds	x6, x10, x5\n\t"
        "adcs	x7, x11, x14\n\t"
        "adcs	x8, x12, x15\n\t"
        "adc	x9, x13, x16\n\t"
        "subs	x24, x24, #1\n\t"
        "b.ne	L_curve25519_inv_3_%=\n\t"
        /* Store */
        "stp	x6, x7, [x29, #144]\n\t"
        "stp	x8, x9, [x29, #160]\n\t"
#ifndef NDEBUG
        "add	x0, x29, #0x70\n\t"
#endif /* !NDEBUG */
        "add	x1, x29, #0x90\n\t"
        "add	x2, x29, #0x70\n\t"
#ifndef __APPLE__
        "bl	fe_mul\n\t"
#else
        "bl	_fe_mul\n\t"
#endif /* __APPLE__ */
        /* Loop: 10 times */
        "mov	x24, #10\n\t"
        "ldp	x6, x7, [x29, #112]\n\t"
        "ldp	x8, x9, [x29, #128]\n\t"
        "\n"
    "L_curve25519_inv_4_%=: \n\t"
        /* Square */
        /*  A[0] * A[1] */
        "umulh	x12, x6, x7\n\t"
        "mul	x11, x6, x7\n\t"
        /*  A[0] * A[3] */
        "umulh	x14, x6, x9\n\t"
        "mul	x13, x6, x9\n\t"
        /*  A[0] * A[2] */
        "mul	x3, x6, x8\n\t"
        "adds	x12, x12, x3\n\t"
        "umulh	x4, x6, x8\n\t"
        "adcs	x13, x13, x4\n\t"
        /*  A[1] * A[3] */
        "mul	x3, x7, x9\n\t"
        "adcs	x14, x14, x3\n\t"
        "umulh	x15, x7, x9\n\t"
        "adc	x15, x15, xzr\n\t"
        /*  A[1] * A[2] */
        "mul	x3, x7, x8\n\t"
        "adds	x13, x13, x3\n\t"
        "umulh	x4, x7, x8\n\t"
        "adcs	x14, x14, x4\n\t"
        /*  A[2] * A[3] */
        "mul	x3, x8, x9\n\t"
        "adcs	x15, x15, x3\n\t"
        "umulh	x16, x8, x9\n\t"
        "adc	x16, x16, xzr\n\t"
        /* Double */
        "adds	x11, x11, x11\n\t"
        "adcs	x12, x12, x12\n\t"
        "adcs	x13, x13, x13\n\t"
        "adcs	x14, x14, x14\n\t"
        "adcs	x15, x15, x15\n\t"
        "adcs	x16, x16, x16\n\t"
        "adc	x17, xzr, xzr\n\t"
        /*  A[0] * A[0] */
        "umulh	x4, x6, x6\n\t"
        "mul	x10, x6, x6\n\t"
        /*  A[1] * A[1] */
        "mul	x3, x7, x7\n\t"
        "adds	x11, x11, x4\n\t"
        "umulh	x4, x7, x7\n\t"
        "adcs	x12, x12, x3\n\t"
        /*  A[2] * A[2] */
        "mul	x3, x8, x8\n\t"
        "adcs	x13, x13, x4\n\t"
        "umulh	x4, x8, x8\n\t"
        "adcs	x14, x14, x3\n\t"
        /*  A[3] * A[3] */
        "mul	x3, x9, x9\n\t"
        "adcs	x15, x15, x4\n\t"
        "umulh	x4, x9, x9\n\t"
        "adcs	x16, x16, x3\n\t"
        "adc	x17, x17, x4\n\t"
        /* Reduce */
        "mov	x3, #38\n\t"
        "mul	x4, x3, x17\n\t"
        "adds	x13, x13, x4\n\t"
        "umulh	x5, x3, x17\n\t"
        "adc	x5, x5, xzr\n\t"
        "mov	x3, #19\n\t"
        "extr	x5, x5, x13, #63\n\t"
        "mul	x5, x5, x3\n\t"
        "and	x13, x13, #0x7fffffffffffffff\n\t"
        "mov	x3, #38\n\t"
        "mul	x4, x3, x14\n\t"
        "adds	x10, x10, x4\n\t"
        "umulh	x14, x3, x14\n\t"
        "mul	x4, x3, x15\n\t"
        "adcs	x11, x11, x4\n\t"
        "umulh	x15, x3, x15\n\t"
        "mul	x4, x3, x16\n\t"
        "adcs	x12, x12, x4\n\t"
        "umulh	x16, x3, x16\n\t"
        "adc	x13, x13, xzr\n\t"
        /*  Add high product results in */
        "adds	x6, x10, x5\n\t"
        "adcs	x7, x11, x14\n\t"
        "adcs	x8, x12, x15\n\t"
        "adc	x9, x13, x16\n\t"
        "subs	x24, x24, #1\n\t"
        "b.ne	L_curve25519_inv_4_%=\n\t"
        /* Store */
        "stp	x6, x7, [x29, #112]\n\t"
        "stp	x8, x9, [x29, #128]\n\t"
        "add	x0, x29, #0x50\n\t"
        "add	x1, x29, #0x70\n\t"
        "add	x2, x29, #0x50\n\t"
#ifndef __APPLE__
        "bl	fe_mul\n\t"
#else
        "bl	_fe_mul\n\t"
#endif /* __APPLE__ */
        /* Loop: 50 times */
        "mov	x24, #50\n\t"
        "ldp	x6, x7, [x29, #80]\n\t"
        "ldp	x8, x9, [x29, #96]\n\t"
        "\n"
    "L_curve25519_inv_5_%=: \n\t"
        /* Square */
        /*  A[0] * A[1] */
        "umulh	x12, x6, x7\n\t"
        "mul	x11, x6, x7\n\t"
        /*  A[0] * A[3] */
        "umulh	x14, x6, x9\n\t"
        "mul	x13, x6, x9\n\t"
        /*  A[0] * A[2] */
        "mul	x3, x6, x8\n\t"
        "adds	x12, x12, x3\n\t"
        "umulh	x4, x6, x8\n\t"
        "adcs	x13, x13, x4\n\t"
        /*  A[1] * A[3] */
        "mul	x3, x7, x9\n\t"
        "adcs	x14, x14, x3\n\t"
        "umulh	x15, x7, x9\n\t"
        "adc	x15, x15, xzr\n\t"
        /*  A[1] * A[2] */
        "mul	x3, x7, x8\n\t"
        "adds	x13, x13, x3\n\t"
        "umulh	x4, x7, x8\n\t"
        "adcs	x14, x14, x4\n\t"
        /*  A[2] * A[3] */
        "mul	x3, x8, x9\n\t"
        "adcs	x15, x15, x3\n\t"
        "umulh	x16, x8, x9\n\t"
        "adc	x16, x16, xzr\n\t"
        /* Double */
        "adds	x11, x11, x11\n\t"
        "adcs	x12, x12, x12\n\t"
        "adcs	x13, x13, x13\n\t"
        "adcs	x14, x14, x14\n\t"
        "adcs	x15, x15, x15\n\t"
        "adcs	x16, x16, x16\n\t"
        "adc	x17, xzr, xzr\n\t"
        /*  A[0] * A[0] */
        "umulh	x4, x6, x6\n\t"
        "mul	x10, x6, x6\n\t"
        /*  A[1] * A[1] */
        "mul	x3, x7, x7\n\t"
        "adds	x11, x11, x4\n\t"
        "umulh	x4, x7, x7\n\t"
        "adcs	x12, x12, x3\n\t"
        /*  A[2] * A[2] */
        "mul	x3, x8, x8\n\t"
        "adcs	x13, x13, x4\n\t"
        "umulh	x4, x8, x8\n\t"
        "adcs	x14, x14, x3\n\t"
        /*  A[3] * A[3] */
        "mul	x3, x9, x9\n\t"
        "adcs	x15, x15, x4\n\t"
        "umulh	x4, x9, x9\n\t"
        "adcs	x16, x16, x3\n\t"
        "adc	x17, x17, x4\n\t"
        /* Reduce */
        "mov	x3, #38\n\t"
        "mul	x4, x3, x17\n\t"
        "adds	x13, x13, x4\n\t"
        "umulh	x5, x3, x17\n\t"
        "adc	x5, x5, xzr\n\t"
        "mov	x3, #19\n\t"
        "extr	x5, x5, x13, #63\n\t"
        "mul	x5, x5, x3\n\t"
        "and	x13, x13, #0x7fffffffffffffff\n\t"
        "mov	x3, #38\n\t"
        "mul	x4, x3, x14\n\t"
        "adds	x10, x10, x4\n\t"
        "umulh	x14, x3, x14\n\t"
        "mul	x4, x3, x15\n\t"
        "adcs	x11, x11, x4\n\t"
        "umulh	x15, x3, x15\n\t"
        "mul	x4, x3, x16\n\t"
        "adcs	x12, x12, x4\n\t"
        "umulh	x16, x3, x16\n\t"
        "adc	x13, x13, xzr\n\t"
        /*  Add high product results in */
        "adds	x6, x10, x5\n\t"
        "adcs	x7, x11, x14\n\t"
        "adcs	x8, x12, x15\n\t"
        "adc	x9, x13, x16\n\t"
        "subs	x24, x24, #1\n\t"
        "b.ne	L_curve25519_inv_5_%=\n\t"
        /* Store */
        "stp	x6, x7, [x29, #112]\n\t"
        "stp	x8, x9, [x29, #128]\n\t"
        "add	x0, x29, #0x70\n\t"
#ifndef NDEBUG
        "add	x1, x29, #0x70\n\t"
#endif /* !NDEBUG */
        "add	x2, x29, #0x50\n\t"
#ifndef __APPLE__
        "bl	fe_mul\n\t"
#else
        "bl	_fe_mul\n\t"
#endif /* __APPLE__ */
        /* Loop: 100 times */
        "mov	x24, #0x64\n\t"
        "ldp	x6, x7, [x29, #112]\n\t"
        "ldp	x8, x9, [x29, #128]\n\t"
        "\n"
    "L_curve25519_inv_6_%=: \n\t"
        /* Square */
        /*  A[0] * A[1] */
        "umulh	x12, x6, x7\n\t"
        "mul	x11, x6, x7\n\t"
        /*  A[0] * A[3] */
        "umulh	x14, x6, x9\n\t"
        "mul	x13, x6, x9\n\t"
        /*  A[0] * A[2] */
        "mul	x3, x6, x8\n\t"
        "adds	x12, x12, x3\n\t"
        "umulh	x4, x6, x8\n\t"
        "adcs	x13, x13, x4\n\t"
        /*  A[1] * A[3] */
        "mul	x3, x7, x9\n\t"
        "adcs	x14, x14, x3\n\t"
        "umulh	x15, x7, x9\n\t"
        "adc	x15, x15, xzr\n\t"
        /*  A[1] * A[2] */
        "mul	x3, x7, x8\n\t"
        "adds	x13, x13, x3\n\t"
        "umulh	x4, x7, x8\n\t"
        "adcs	x14, x14, x4\n\t"
        /*  A[2] * A[3] */
        "mul	x3, x8, x9\n\t"
        "adcs	x15, x15, x3\n\t"
        "umulh	x16, x8, x9\n\t"
        "adc	x16, x16, xzr\n\t"
        /* Double */
        "adds	x11, x11, x11\n\t"
        "adcs	x12, x12, x12\n\t"
        "adcs	x13, x13, x13\n\t"
        "adcs	x14, x14, x14\n\t"
        "adcs	x15, x15, x15\n\t"
        "adcs	x16, x16, x16\n\t"
        "adc	x17, xzr, xzr\n\t"
        /*  A[0] * A[0] */
        "umulh	x4, x6, x6\n\t"
        "mul	x10, x6, x6\n\t"
        /*  A[1] * A[1] */
        "mul	x3, x7, x7\n\t"
        "adds	x11, x11, x4\n\t"
        "umulh	x4, x7, x7\n\t"
        "adcs	x12, x12, x3\n\t"
        /*  A[2] * A[2] */
        "mul	x3, x8, x8\n\t"
        "adcs	x13, x13, x4\n\t"
        "umulh	x4, x8, x8\n\t"
        "adcs	x14, x14, x3\n\t"
        /*  A[3] * A[3] */
        "mul	x3, x9, x9\n\t"
        "adcs	x15, x15, x4\n\t"
        "umulh	x4, x9, x9\n\t"
        "adcs	x16, x16, x3\n\t"
        "adc	x17, x17, x4\n\t"
        /* Reduce */
        "mov	x3, #38\n\t"
        "mul	x4, x3, x17\n\t"
        "adds	x13, x13, x4\n\t"
        "umulh	x5, x3, x17\n\t"
        "adc	x5, x5, xzr\n\t"
        "mov	x3, #19\n\t"
        "extr	x5, x5, x13, #63\n\t"
        "mul	x5, x5, x3\n\t"
        "and	x13, x13, #0x7fffffffffffffff\n\t"
        "mov	x3, #38\n\t"
        "mul	x4, x3, x14\n\t"
        "adds	x10, x10, x4\n\t"
        "umulh	x14, x3, x14\n\t"
        "mul	x4, x3, x15\n\t"
        "adcs	x11, x11, x4\n\t"
        "umulh	x15, x3, x15\n\t"
        "mul	x4, x3, x16\n\t"
        "adcs	x12, x12, x4\n\t"
        "umulh	x16, x3, x16\n\t"
        "adc	x13, x13, xzr\n\t"
        /*  Add high product results in */
        "adds	x6, x10, x5\n\t"
        "adcs	x7, x11, x14\n\t"
        "adcs	x8, x12, x15\n\t"
        "adc	x9, x13, x16\n\t"
        "subs	x24, x24, #1\n\t"
        "b.ne	L_curve25519_inv_6_%=\n\t"
        /* Store */
        "stp	x6, x7, [x29, #144]\n\t"
        "stp	x8, x9, [x29, #160]\n\t"
#ifndef NDEBUG
        "add	x0, x29, #0x70\n\t"
#endif /* !NDEBUG */
        "add	x1, x29, #0x90\n\t"
        "add	x2, x29, #0x70\n\t"
#ifndef __APPLE__
        "bl	fe_mul\n\t"
#else
        "bl	_fe_mul\n\t"
#endif /* __APPLE__ */
        /* Loop: 50 times */
        "mov	x24, #50\n\t"
        "ldp	x6, x7, [x29, #112]\n\t"
        "ldp	x8, x9, [x29, #128]\n\t"
        "\n"
    "L_curve25519_inv_7_%=: \n\t"
        /* Square */
        /*  A[0] * A[1] */
        "umulh	x12, x6, x7\n\t"
        "mul	x11, x6, x7\n\t"
        /*  A[0] * A[3] */
        "umulh	x14, x6, x9\n\t"
        "mul	x13, x6, x9\n\t"
        /*  A[0] * A[2] */
        "mul	x3, x6, x8\n\t"
        "adds	x12, x12, x3\n\t"
        "umulh	x4, x6, x8\n\t"
        "adcs	x13, x13, x4\n\t"
        /*  A[1] * A[3] */
        "mul	x3, x7, x9\n\t"
        "adcs	x14, x14, x3\n\t"
        "umulh	x15, x7, x9\n\t"
        "adc	x15, x15, xzr\n\t"
        /*  A[1] * A[2] */
        "mul	x3, x7, x8\n\t"
        "adds	x13, x13, x3\n\t"
        "umulh	x4, x7, x8\n\t"
        "adcs	x14, x14, x4\n\t"
        /*  A[2] * A[3] */
        "mul	x3, x8, x9\n\t"
        "adcs	x15, x15, x3\n\t"
        "umulh	x16, x8, x9\n\t"
        "adc	x16, x16, xzr\n\t"
        /* Double */
        "adds	x11, x11, x11\n\t"
        "adcs	x12, x12, x12\n\t"
        "adcs	x13, x13, x13\n\t"
        "adcs	x14, x14, x14\n\t"
        "adcs	x15, x15, x15\n\t"
        "adcs	x16, x16, x16\n\t"
        "adc	x17, xzr, xzr\n\t"
        /*  A[0] * A[0] */
        "umulh	x4, x6, x6\n\t"
        "mul	x10, x6, x6\n\t"
        /*  A[1] * A[1] */
        "mul	x3, x7, x7\n\t"
        "adds	x11, x11, x4\n\t"
        "umulh	x4, x7, x7\n\t"
        "adcs	x12, x12, x3\n\t"
        /*  A[2] * A[2] */
        "mul	x3, x8, x8\n\t"
        "adcs	x13, x13, x4\n\t"
        "umulh	x4, x8, x8\n\t"
        "adcs	x14, x14, x3\n\t"
        /*  A[3] * A[3] */
        "mul	x3, x9, x9\n\t"
        "adcs	x15, x15, x4\n\t"
        "umulh	x4, x9, x9\n\t"
        "adcs	x16, x16, x3\n\t"
        "adc	x17, x17, x4\n\t"
        /* Reduce */
        "mov	x3, #38\n\t"
        "mul	x4, x3, x17\n\t"
        "adds	x13, x13, x4\n\t"
        "umulh	x5, x3, x17\n\t"
        "adc	x5, x5, xzr\n\t"
        "mov	x3, #19\n\t"
        "extr	x5, x5, x13, #63\n\t"
        "mul	x5, x5, x3\n\t"
        "and	x13, x13, #0x7fffffffffffffff\n\t"
        "mov	x3, #38\n\t"
        "mul	x4, x3, x14\n\t"
        "adds	x10, x10, x4\n\t"
        "umulh	x14, x3, x14\n\t"
        "mul	x4, x3, x15\n\t"
        "adcs	x11, x11, x4\n\t"
        "umulh	x15, x3, x15\n\t"
        "mul	x4, x3, x16\n\t"
        "adcs	x12, x12, x4\n\t"
        "umulh	x16, x3, x16\n\t"
        "adc	x13, x13, xzr\n\t"
        /*  Add high product results in */
        "adds	x6, x10, x5\n\t"
        "adcs	x7, x11, x14\n\t"
        "adcs	x8, x12, x15\n\t"
        "adc	x9, x13, x16\n\t"
        "subs	x24, x24, #1\n\t"
        "b.ne	L_curve25519_inv_7_%=\n\t"
        /* Store */
        "stp	x6, x7, [x29, #112]\n\t"
        "stp	x8, x9, [x29, #128]\n\t"
        "add	x0, x29, #0x50\n\t"
        "add	x1, x29, #0x70\n\t"
        "add	x2, x29, #0x50\n\t"
#ifndef __APPLE__
        "bl	fe_mul\n\t"
#else
        "bl	_fe_mul\n\t"
#endif /* __APPLE__ */
        /* Loop: 5 times */
        "mov	x24, #5\n\t"
        "ldp	x6, x7, [x29, #80]\n\t"
        "ldp	x8, x9, [x29, #96]\n\t"
        "\n"
    "L_curve25519_inv_8_%=: \n\t"
        /* Square */
        /*  A[0] * A[1] */
        "umulh	x12, x6, x7\n\t"
        "mul	x11, x6, x7\n\t"
        /*  A[0] * A[3] */
        "umulh	x14, x6, x9\n\t"
        "mul	x13, x6, x9\n\t"
        /*  A[0] * A[2] */
        "mul	x3, x6, x8\n\t"
        "adds	x12, x12, x3\n\t"
        "umulh	x4, x6, x8\n\t"
        "adcs	x13, x13, x4\n\t"
        /*  A[1] * A[3] */
        "mul	x3, x7, x9\n\t"
        "adcs	x14, x14, x3\n\t"
        "umulh	x15, x7, x9\n\t"
        "adc	x15, x15, xzr\n\t"
        /*  A[1] * A[2] */
        "mul	x3, x7, x8\n\t"
        "adds	x13, x13, x3\n\t"
        "umulh	x4, x7, x8\n\t"
        "adcs	x14, x14, x4\n\t"
        /*  A[2] * A[3] */
        "mul	x3, x8, x9\n\t"
        "adcs	x15, x15, x3\n\t"
        "umulh	x16, x8, x9\n\t"
        "adc	x16, x16, xzr\n\t"
        /* Double */
        "adds	x11, x11, x11\n\t"
        "adcs	x12, x12, x12\n\t"
        "adcs	x13, x13, x13\n\t"
        "adcs	x14, x14, x14\n\t"
        "adcs	x15, x15, x15\n\t"
        "adcs	x16, x16, x16\n\t"
        "adc	x17, xzr, xzr\n\t"
        /*  A[0] * A[0] */
        "umulh	x4, x6, x6\n\t"
        "mul	x10, x6, x6\n\t"
        /*  A[1] * A[1] */
        "mul	x3, x7, x7\n\t"
        "adds	x11, x11, x4\n\t"
        "umulh	x4, x7, x7\n\t"
        "adcs	x12, x12, x3\n\t"
        /*  A[2] * A[2] */
        "mul	x3, x8, x8\n\t"
        "adcs	x13, x13, x4\n\t"
        "umulh	x4, x8, x8\n\t"
        "adcs	x14, x14, x3\n\t"
        /*  A[3] * A[3] */
        "mul	x3, x9, x9\n\t"
        "adcs	x15, x15, x4\n\t"
        "umulh	x4, x9, x9\n\t"
        "adcs	x16, x16, x3\n\t"
        "adc	x17, x17, x4\n\t"
        /* Reduce */
        "mov	x3, #38\n\t"
        "mul	x4, x3, x17\n\t"
        "adds	x13, x13, x4\n\t"
        "umulh	x5, x3, x17\n\t"
        "adc	x5, x5, xzr\n\t"
        "mov	x3, #19\n\t"
        "extr	x5, x5, x13, #63\n\t"
        "mul	x5, x5, x3\n\t"
        "and	x13, x13, #0x7fffffffffffffff\n\t"
        "mov	x3, #38\n\t"
        "mul	x4, x3, x14\n\t"
        "adds	x10, x10, x4\n\t"
        "umulh	x14, x3, x14\n\t"
        "mul	x4, x3, x15\n\t"
        "adcs	x11, x11, x4\n\t"
        "umulh	x15, x3, x15\n\t"
        "mul	x4, x3, x16\n\t"
        "adcs	x12, x12, x4\n\t"
        "umulh	x16, x3, x16\n\t"
        "adc	x13, x13, xzr\n\t"
        /*  Add high product results in */
        "adds	x6, x10, x5\n\t"
        "adcs	x7, x11, x14\n\t"
        "adcs	x8, x12, x15\n\t"
        "adc	x9, x13, x16\n\t"
        "subs	x24, x24, #1\n\t"
        "b.ne	L_curve25519_inv_8_%=\n\t"
        /* Store */
        "stp	x6, x7, [x29, #80]\n\t"
        "stp	x8, x9, [x29, #96]\n\t"
        "add	x0, x29, #16\n\t"
        "add	x1, x29, #0x50\n\t"
        "add	x2, x29, #48\n\t"
#ifndef __APPLE__
        "bl	fe_mul\n\t"
#else
        "bl	_fe_mul\n\t"
#endif /* __APPLE__ */
        "ldr	%x[r], [x29, #176]\n\t"
        /* Multiply */
        "ldp	x6, x7, [%x[r]]\n\t"
        "ldp	x8, x9, [%x[r], #16]\n\t"
        "ldp	x10, x11, [x29, #16]\n\t"
        "ldp	x12, x13, [x29, #32]\n\t"
        /* A[0] * B[0] */
        "umulh	x15, x6, x10\n\t"
        "mul	x14, x6, x10\n\t"
        /* A[2] * B[0] */
        "umulh	x17, x8, x10\n\t"
        "mul	x16, x8, x10\n\t"
        /* A[1] * B[0] */
        "mul	x3, x7, x10\n\t"
        "adds	x15, x15, x3\n\t"
        "umulh	x4, x7, x10\n\t"
        "adcs	x16, x16, x4\n\t"
        /* A[1] * B[3] */
        "umulh	x20, x7, x13\n\t"
        "adc	x17, x17, xzr\n\t"
        "mul	x19, x7, x13\n\t"
        /* A[0] * B[1] */
        "mul	x3, x6, x11\n\t"
        "adds	x15, x15, x3\n\t"
        "umulh	x4, x6, x11\n\t"
        "adcs	x16, x16, x4\n\t"
        /* A[2] * B[1] */
        "mul	x3, x8, x11\n\t"
        "adcs	x17, x17, x3\n\t"
        "umulh	x4, x8, x11\n\t"
        "adcs	x19, x19, x4\n\t"
        "adc	x20, x20, xzr\n\t"
        /* A[1] * B[2] */
        "mul	x3, x7, x12\n\t"
        "adds	x17, x17, x3\n\t"
        "umulh	x4, x7, x12\n\t"
        "adcs	x19, x19, x4\n\t"
        "adcs	x20, x20, xzr\n\t"
        "adc	x21, xzr, xzr\n\t"
        /* A[0] * B[2] */
        "mul	x3, x6, x12\n\t"
        "adds	x16, x16, x3\n\t"
        "umulh	x4, x6, x12\n\t"
        "adcs	x17, x17, x4\n\t"
        "adcs	x19, x19, xzr\n\t"
        "adcs	x20, x20, xzr\n\t"
        "adc	x21, x21, xzr\n\t"
        /* A[1] * B[1] */
        "mul	x3, x7, x11\n\t"
        "adds	x16, x16, x3\n\t"
        "umulh	x4, x7, x11\n\t"
        "adcs	x17, x17, x4\n\t"
        /* A[3] * B[1] */
        "mul	x3, x9, x11\n\t"
        "adcs	x19, x19, x3\n\t"
        "umulh	x4, x9, x11\n\t"
        "adcs	x20, x20, x4\n\t"
        "adc	x21, x21, xzr\n\t"
        /* A[2] * B[2] */
        "mul	x3, x8, x12\n\t"
        "adds	x19, x19, x3\n\t"
        "umulh	x4, x8, x12\n\t"
        "adcs	x20, x20, x4\n\t"
        /* A[3] * B[3] */
        "mul	x3, x9, x13\n\t"
        "adcs	x21, x21, x3\n\t"
        "umulh	x22, x9, x13\n\t"
        "adc	x22, x22, xzr\n\t"
        /* A[0] * B[3] */
        "mul	x3, x6, x13\n\t"
        "adds	x17, x17, x3\n\t"
        "umulh	x4, x6, x13\n\t"
        "adcs	x19, x19, x4\n\t"
        /* A[2] * B[3] */
        "mul	x3, x8, x13\n\t"
        "adcs	x20, x20, x3\n\t"
        "umulh	x4, x8, x13\n\t"
        "adcs	x21, x21, x4\n\t"
        "adc	x22, x22, xzr\n\t"
        /* A[3] * B[0] */
        "mul	x3, x9, x10\n\t"
        "adds	x17, x17, x3\n\t"
        "umulh	x4, x9, x10\n\t"
        "adcs	x19, x19, x4\n\t"
        /* A[3] * B[2] */
        "mul	x3, x9, x12\n\t"
        "adcs	x20, x20, x3\n\t"
        "umulh	x4, x9, x12\n\t"
        "adcs	x21, x21, x4\n\t"
        "adc	x22, x22, xzr\n\t"
        /* Reduce */
        "mov	x3, #38\n\t"
        "mul	x4, x3, x22\n\t"
        "adds	x17, x17, x4\n\t"
        "umulh	x5, x3, x22\n\t"
        "adc	x5, x5, xzr\n\t"
        "mov	x3, #19\n\t"
        "extr	x5, x5, x17, #63\n\t"
        "mul	x5, x5, x3\n\t"
        "and	x17, x17, #0x7fffffffffffffff\n\t"
        "mov	x3, #38\n\t"
        "mul	x4, x3, x19\n\t"
        "adds	x14, x14, x4\n\t"
        "umulh	x19, x3, x19\n\t"
        "mul	x4, x3, x20\n\t"
        "adcs	x15, x15, x4\n\t"
        "umulh	x20, x3, x20\n\t"
        "mul	x4, x3, x21\n\t"
        "adcs	x16, x16, x4\n\t"
        "umulh	x21, x3, x21\n\t"
        "adc	x17, x17, xzr\n\t"
        /*  Add high product results in */
        "adds	x14, x14, x5\n\t"
        "adcs	x15, x15, x19\n\t"
        "adcs	x16, x16, x20\n\t"
        "adc	x17, x17, x21\n\t"
        /* Reduce if top bit set */
        "mov	x3, #19\n\t"
        "and	x4, x3, x17, asr 63\n\t"
        "adds	x14, x14, x4\n\t"
        "adcs	x15, x15, xzr\n\t"
        "and	x17, x17, #0x7fffffffffffffff\n\t"
        "adcs	x16, x16, xzr\n\t"
        "adc	x17, x17, xzr\n\t"
        "adds	x4, x14, x3\n\t"
        "adcs	x4, x15, xzr\n\t"
        "adcs	x4, x16, xzr\n\t"
        "adc	x4, x17, xzr\n\t"
        "and	x4, x3, x4, asr 63\n\t"
        "adds	x14, x14, x4\n\t"
        "adcs	x15, x15, xzr\n\t"
        "mov	x4, #0x7fffffffffffffff\n\t"
        "adcs	x16, x16, xzr\n\t"
        "adc	x17, x17, xzr\n\t"
        "and	x17, x17, x4\n\t"
        /* Store */
        "stp	x14, x15, [%x[r]]\n\t"
        "stp	x16, x17, [%x[r], #16]\n\t"
        "mov	x0, xzr\n\t"
        "ldp	x29, x30, [sp], #0xc0\n\t"
        : [r] "+r" (r)
        : [n] "r" (n), [a] "r" (a)
        : "memory", "cc", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10",
            "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20",
            "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28"
    );
    return (word32)(size_t)r;
}

#ifdef HAVE_ED25519
void fe_pow22523(fe r, const fe a)
{
    __asm__ __volatile__ (
        "stp	x29, x30, [sp, #-128]!\n\t"
        "add	x29, sp, #0\n\t"
        /* pow22523 */
        "str	%x[r], [x29, #112]\n\t"
        "str	%x[a], [x29, #120]\n\t"
        "add	x0, x29, #16\n\t"
#ifndef NDEBUG
        "ldr	x1, [x29, #120]\n\t"
#endif /* !NDEBUG */
#ifndef __APPLE__
        "bl	fe_sq\n\t"
#else
        "bl	_fe_sq\n\t"
#endif /* __APPLE__ */
        "add	x0, x29, #48\n\t"
        "add	x1, x29, #16\n\t"
#ifndef __APPLE__
        "bl	fe_sq\n\t"
#else
        "bl	_fe_sq\n\t"
#endif /* __APPLE__ */
#ifndef NDEBUG
        "add	x0, x29, #48\n\t"
#endif /* !NDEBUG */
        "add	x1, x29, #48\n\t"
#ifndef __APPLE__
        "bl	fe_sq\n\t"
#else
        "bl	_fe_sq\n\t"
#endif /* __APPLE__ */
#ifndef NDEBUG
        "add	x0, x29, #48\n\t"
#endif /* !NDEBUG */
        "ldr	x1, [x29, #120]\n\t"
        "add	x2, x29, #48\n\t"
#ifndef __APPLE__
        "bl	fe_mul\n\t"
#else
        "bl	_fe_mul\n\t"
#endif /* __APPLE__ */
        "add	x0, x29, #16\n\t"
        "add	x1, x29, #16\n\t"
        "add	x2, x29, #48\n\t"
#ifndef __APPLE__
        "bl	fe_mul\n\t"
#else
        "bl	_fe_mul\n\t"
#endif /* __APPLE__ */
#ifndef NDEBUG
        "add	x0, x29, #16\n\t"
#endif /* !NDEBUG */
#ifndef NDEBUG
        "add	x1, x29, #16\n\t"
#endif /* !NDEBUG */
#ifndef __APPLE__
        "bl	fe_sq\n\t"
#else
        "bl	_fe_sq\n\t"
#endif /* __APPLE__ */
#ifndef NDEBUG
        "add	x0, x29, #16\n\t"
#endif /* !NDEBUG */
        "add	x1, x29, #48\n\t"
        "add	x2, x29, #16\n\t"
#ifndef __APPLE__
        "bl	fe_mul\n\t"
#else
        "bl	_fe_mul\n\t"
#endif /* __APPLE__ */
        /* Loop: 5 times */
        "mov	x23, #5\n\t"
        "ldp	x6, x7, [x29, #16]\n\t"
        "ldp	x8, x9, [x29, #32]\n\t"
        "\n"
    "L_fe_pow22523_1_%=: \n\t"
        /* Square */
        /*  A[0] * A[1] */
        "umulh	x12, x6, x7\n\t"
        "mul	x11, x6, x7\n\t"
        /*  A[0] * A[3] */
        "umulh	x14, x6, x9\n\t"
        "mul	x13, x6, x9\n\t"
        /*  A[0] * A[2] */
        "mul	x3, x6, x8\n\t"
        "adds	x12, x12, x3\n\t"
        "umulh	x4, x6, x8\n\t"
        "adcs	x13, x13, x4\n\t"
        /*  A[1] * A[3] */
        "mul	x3, x7, x9\n\t"
        "adcs	x14, x14, x3\n\t"
        "umulh	x15, x7, x9\n\t"
        "adc	x15, x15, xzr\n\t"
        /*  A[1] * A[2] */
        "mul	x3, x7, x8\n\t"
        "adds	x13, x13, x3\n\t"
        "umulh	x4, x7, x8\n\t"
        "adcs	x14, x14, x4\n\t"
        /*  A[2] * A[3] */
        "mul	x3, x8, x9\n\t"
        "adcs	x15, x15, x3\n\t"
        "umulh	x16, x8, x9\n\t"
        "adc	x16, x16, xzr\n\t"
        /* Double */
        "adds	x11, x11, x11\n\t"
        "adcs	x12, x12, x12\n\t"
        "adcs	x13, x13, x13\n\t"
        "adcs	x14, x14, x14\n\t"
        "adcs	x15, x15, x15\n\t"
        "adcs	x16, x16, x16\n\t"
        "adc	x17, xzr, xzr\n\t"
        /*  A[0] * A[0] */
        "umulh	x4, x6, x6\n\t"
        "mul	x10, x6, x6\n\t"
        /*  A[1] * A[1] */
        "mul	x3, x7, x7\n\t"
        "adds	x11, x11, x4\n\t"
        "umulh	x4, x7, x7\n\t"
        "adcs	x12, x12, x3\n\t"
        /*  A[2] * A[2] */
        "mul	x3, x8, x8\n\t"
        "adcs	x13, x13, x4\n\t"
        "umulh	x4, x8, x8\n\t"
        "adcs	x14, x14, x3\n\t"
        /*  A[3] * A[3] */
        "mul	x3, x9, x9\n\t"
        "adcs	x15, x15, x4\n\t"
        "umulh	x4, x9, x9\n\t"
        "adcs	x16, x16, x3\n\t"
        "adc	x17, x17, x4\n\t"
        /* Reduce */
        "mov	x3, #38\n\t"
        "mul	x4, x3, x17\n\t"
        "adds	x13, x13, x4\n\t"
        "umulh	x5, x3, x17\n\t"
        "adc	x5, x5, xzr\n\t"
        "mov	x3, #19\n\t"
        "extr	x5, x5, x13, #63\n\t"
        "mul	x5, x5, x3\n\t"
        "and	x13, x13, #0x7fffffffffffffff\n\t"
        "mov	x3, #38\n\t"
        "mul	x4, x3, x14\n\t"
        "adds	x10, x10, x4\n\t"
        "umulh	x14, x3, x14\n\t"
        "mul	x4, x3, x15\n\t"
        "adcs	x11, x11, x4\n\t"
        "umulh	x15, x3, x15\n\t"
        "mul	x4, x3, x16\n\t"
        "adcs	x12, x12, x4\n\t"
        "umulh	x16, x3, x16\n\t"
        "adc	x13, x13, xzr\n\t"
        /*  Add high product results in */
        "adds	x6, x10, x5\n\t"
        "adcs	x7, x11, x14\n\t"
        "adcs	x8, x12, x15\n\t"
        "adc	x9, x13, x16\n\t"
        "subs	x23, x23, #1\n\t"
        "b.ne	L_fe_pow22523_1_%=\n\t"
        /* Store */
        "stp	x6, x7, [x29, #48]\n\t"
        "stp	x8, x9, [x29, #64]\n\t"
#ifndef NDEBUG
        "add	x0, x29, #16\n\t"
#endif /* !NDEBUG */
#ifndef NDEBUG
        "add	x1, x29, #48\n\t"
#endif /* !NDEBUG */
        "add	x2, x29, #16\n\t"
#ifndef __APPLE__
        "bl	fe_mul\n\t"
#else
        "bl	_fe_mul\n\t"
#endif /* __APPLE__ */
        /* Loop: 10 times */
        "mov	x23, #10\n\t"
        "ldp	x6, x7, [x29, #16]\n\t"
        "ldp	x8, x9, [x29, #32]\n\t"
        "\n"
    "L_fe_pow22523_2_%=: \n\t"
        /* Square */
        /*  A[0] * A[1] */
        "umulh	x12, x6, x7\n\t"
        "mul	x11, x6, x7\n\t"
        /*  A[0] * A[3] */
        "umulh	x14, x6, x9\n\t"
        "mul	x13, x6, x9\n\t"
        /*  A[0] * A[2] */
        "mul	x3, x6, x8\n\t"
        "adds	x12, x12, x3\n\t"
        "umulh	x4, x6, x8\n\t"
        "adcs	x13, x13, x4\n\t"
        /*  A[1] * A[3] */
        "mul	x3, x7, x9\n\t"
        "adcs	x14, x14, x3\n\t"
        "umulh	x15, x7, x9\n\t"
        "adc	x15, x15, xzr\n\t"
        /*  A[1] * A[2] */
        "mul	x3, x7, x8\n\t"
        "adds	x13, x13, x3\n\t"
        "umulh	x4, x7, x8\n\t"
        "adcs	x14, x14, x4\n\t"
        /*  A[2] * A[3] */
        "mul	x3, x8, x9\n\t"
        "adcs	x15, x15, x3\n\t"
        "umulh	x16, x8, x9\n\t"
        "adc	x16, x16, xzr\n\t"
        /* Double */
        "adds	x11, x11, x11\n\t"
        "adcs	x12, x12, x12\n\t"
        "adcs	x13, x13, x13\n\t"
        "adcs	x14, x14, x14\n\t"
        "adcs	x15, x15, x15\n\t"
        "adcs	x16, x16, x16\n\t"
        "adc	x17, xzr, xzr\n\t"
        /*  A[0] * A[0] */
        "umulh	x4, x6, x6\n\t"
        "mul	x10, x6, x6\n\t"
        /*  A[1] * A[1] */
        "mul	x3, x7, x7\n\t"
        "adds	x11, x11, x4\n\t"
        "umulh	x4, x7, x7\n\t"
        "adcs	x12, x12, x3\n\t"
        /*  A[2] * A[2] */
        "mul	x3, x8, x8\n\t"
        "adcs	x13, x13, x4\n\t"
        "umulh	x4, x8, x8\n\t"
        "adcs	x14, x14, x3\n\t"
        /*  A[3] * A[3] */
        "mul	x3, x9, x9\n\t"
        "adcs	x15, x15, x4\n\t"
        "umulh	x4, x9, x9\n\t"
        "adcs	x16, x16, x3\n\t"
        "adc	x17, x17, x4\n\t"
        /* Reduce */
        "mov	x3, #38\n\t"
        "mul	x4, x3, x17\n\t"
        "adds	x13, x13, x4\n\t"
        "umulh	x5, x3, x17\n\t"
        "adc	x5, x5, xzr\n\t"
        "mov	x3, #19\n\t"
        "extr	x5, x5, x13, #63\n\t"
        "mul	x5, x5, x3\n\t"
        "and	x13, x13, #0x7fffffffffffffff\n\t"
        "mov	x3, #38\n\t"
        "mul	x4, x3, x14\n\t"
        "adds	x10, x10, x4\n\t"
        "umulh	x14, x3, x14\n\t"
        "mul	x4, x3, x15\n\t"
        "adcs	x11, x11, x4\n\t"
        "umulh	x15, x3, x15\n\t"
        "mul	x4, x3, x16\n\t"
        "adcs	x12, x12, x4\n\t"
        "umulh	x16, x3, x16\n\t"
        "adc	x13, x13, xzr\n\t"
        /*  Add high product results in */
        "adds	x6, x10, x5\n\t"
        "adcs	x7, x11, x14\n\t"
        "adcs	x8, x12, x15\n\t"
        "adc	x9, x13, x16\n\t"
        "subs	x23, x23, #1\n\t"
        "b.ne	L_fe_pow22523_2_%=\n\t"
        /* Store */
        "stp	x6, x7, [x29, #48]\n\t"
        "stp	x8, x9, [x29, #64]\n\t"
        "add	x0, x29, #48\n\t"
#ifndef NDEBUG
        "add	x1, x29, #48\n\t"
#endif /* !NDEBUG */
        "add	x2, x29, #16\n\t"
#ifndef __APPLE__
        "bl	fe_mul\n\t"
#else
        "bl	_fe_mul\n\t"
#endif /* __APPLE__ */
        /* Loop: 20 times */
        "mov	x23, #20\n\t"
        "ldp	x6, x7, [x29, #48]\n\t"
        "ldp	x8, x9, [x29, #64]\n\t"
        "\n"
    "L_fe_pow22523_3_%=: \n\t"
        /* Square */
        /*  A[0] * A[1] */
        "umulh	x12, x6, x7\n\t"
        "mul	x11, x6, x7\n\t"
        /*  A[0] * A[3] */
        "umulh	x14, x6, x9\n\t"
        "mul	x13, x6, x9\n\t"
        /*  A[0] * A[2] */
        "mul	x3, x6, x8\n\t"
        "adds	x12, x12, x3\n\t"
        "umulh	x4, x6, x8\n\t"
        "adcs	x13, x13, x4\n\t"
        /*  A[1] * A[3] */
        "mul	x3, x7, x9\n\t"
        "adcs	x14, x14, x3\n\t"
        "umulh	x15, x7, x9\n\t"
        "adc	x15, x15, xzr\n\t"
        /*  A[1] * A[2] */
        "mul	x3, x7, x8\n\t"
        "adds	x13, x13, x3\n\t"
        "umulh	x4, x7, x8\n\t"
        "adcs	x14, x14, x4\n\t"
        /*  A[2] * A[3] */
        "mul	x3, x8, x9\n\t"
        "adcs	x15, x15, x3\n\t"
        "umulh	x16, x8, x9\n\t"
        "adc	x16, x16, xzr\n\t"
        /* Double */
        "adds	x11, x11, x11\n\t"
        "adcs	x12, x12, x12\n\t"
        "adcs	x13, x13, x13\n\t"
        "adcs	x14, x14, x14\n\t"
        "adcs	x15, x15, x15\n\t"
        "adcs	x16, x16, x16\n\t"
        "adc	x17, xzr, xzr\n\t"
        /*  A[0] * A[0] */
        "umulh	x4, x6, x6\n\t"
        "mul	x10, x6, x6\n\t"
        /*  A[1] * A[1] */
        "mul	x3, x7, x7\n\t"
        "adds	x11, x11, x4\n\t"
        "umulh	x4, x7, x7\n\t"
        "adcs	x12, x12, x3\n\t"
        /*  A[2] * A[2] */
        "mul	x3, x8, x8\n\t"
        "adcs	x13, x13, x4\n\t"
        "umulh	x4, x8, x8\n\t"
        "adcs	x14, x14, x3\n\t"
        /*  A[3] * A[3] */
        "mul	x3, x9, x9\n\t"
        "adcs	x15, x15, x4\n\t"
        "umulh	x4, x9, x9\n\t"
        "adcs	x16, x16, x3\n\t"
        "adc	x17, x17, x4\n\t"
        /* Reduce */
        "mov	x3, #38\n\t"
        "mul	x4, x3, x17\n\t"
        "adds	x13, x13, x4\n\t"
        "umulh	x5, x3, x17\n\t"
        "adc	x5, x5, xzr\n\t"
        "mov	x3, #19\n\t"
        "extr	x5, x5, x13, #63\n\t"
        "mul	x5, x5, x3\n\t"
        "and	x13, x13, #0x7fffffffffffffff\n\t"
        "mov	x3, #38\n\t"
        "mul	x4, x3, x14\n\t"
        "adds	x10, x10, x4\n\t"
        "umulh	x14, x3, x14\n\t"
        "mul	x4, x3, x15\n\t"
        "adcs	x11, x11, x4\n\t"
        "umulh	x15, x3, x15\n\t"
        "mul	x4, x3, x16\n\t"
        "adcs	x12, x12, x4\n\t"
        "umulh	x16, x3, x16\n\t"
        "adc	x13, x13, xzr\n\t"
        /*  Add high product results in */
        "adds	x6, x10, x5\n\t"
        "adcs	x7, x11, x14\n\t"
        "adcs	x8, x12, x15\n\t"
        "adc	x9, x13, x16\n\t"
        "subs	x23, x23, #1\n\t"
        "b.ne	L_fe_pow22523_3_%=\n\t"
        /* Store */
        "stp	x6, x7, [x29, #80]\n\t"
        "stp	x8, x9, [x29, #96]\n\t"
#ifndef NDEBUG
        "add	x0, x29, #48\n\t"
#endif /* !NDEBUG */
        "add	x1, x29, #0x50\n\t"
        "add	x2, x29, #48\n\t"
#ifndef __APPLE__
        "bl	fe_mul\n\t"
#else
        "bl	_fe_mul\n\t"
#endif /* __APPLE__ */
        /* Loop: 10 times */
        "mov	x23, #10\n\t"
        "ldp	x6, x7, [x29, #48]\n\t"
        "ldp	x8, x9, [x29, #64]\n\t"
        "\n"
    "L_fe_pow22523_4_%=: \n\t"
        /* Square */
        /*  A[0] * A[1] */
        "umulh	x12, x6, x7\n\t"
        "mul	x11, x6, x7\n\t"
        /*  A[0] * A[3] */
        "umulh	x14, x6, x9\n\t"
        "mul	x13, x6, x9\n\t"
        /*  A[0] * A[2] */
        "mul	x3, x6, x8\n\t"
        "adds	x12, x12, x3\n\t"
        "umulh	x4, x6, x8\n\t"
        "adcs	x13, x13, x4\n\t"
        /*  A[1] * A[3] */
        "mul	x3, x7, x9\n\t"
        "adcs	x14, x14, x3\n\t"
        "umulh	x15, x7, x9\n\t"
        "adc	x15, x15, xzr\n\t"
        /*  A[1] * A[2] */
        "mul	x3, x7, x8\n\t"
        "adds	x13, x13, x3\n\t"
        "umulh	x4, x7, x8\n\t"
        "adcs	x14, x14, x4\n\t"
        /*  A[2] * A[3] */
        "mul	x3, x8, x9\n\t"
        "adcs	x15, x15, x3\n\t"
        "umulh	x16, x8, x9\n\t"
        "adc	x16, x16, xzr\n\t"
        /* Double */
        "adds	x11, x11, x11\n\t"
        "adcs	x12, x12, x12\n\t"
        "adcs	x13, x13, x13\n\t"
        "adcs	x14, x14, x14\n\t"
        "adcs	x15, x15, x15\n\t"
        "adcs	x16, x16, x16\n\t"
        "adc	x17, xzr, xzr\n\t"
        /*  A[0] * A[0] */
        "umulh	x4, x6, x6\n\t"
        "mul	x10, x6, x6\n\t"
        /*  A[1] * A[1] */
        "mul	x3, x7, x7\n\t"
        "adds	x11, x11, x4\n\t"
        "umulh	x4, x7, x7\n\t"
        "adcs	x12, x12, x3\n\t"
        /*  A[2] * A[2] */
        "mul	x3, x8, x8\n\t"
        "adcs	x13, x13, x4\n\t"
        "umulh	x4, x8, x8\n\t"
        "adcs	x14, x14, x3\n\t"
        /*  A[3] * A[3] */
        "mul	x3, x9, x9\n\t"
        "adcs	x15, x15, x4\n\t"
        "umulh	x4, x9, x9\n\t"
        "adcs	x16, x16, x3\n\t"
        "adc	x17, x17, x4\n\t"
        /* Reduce */
        "mov	x3, #38\n\t"
        "mul	x4, x3, x17\n\t"
        "adds	x13, x13, x4\n\t"
        "umulh	x5, x3, x17\n\t"
        "adc	x5, x5, xzr\n\t"
        "mov	x3, #19\n\t"
        "extr	x5, x5, x13, #63\n\t"
        "mul	x5, x5, x3\n\t"
        "and	x13, x13, #0x7fffffffffffffff\n\t"
        "mov	x3, #38\n\t"
        "mul	x4, x3, x14\n\t"
        "adds	x10, x10, x4\n\t"
        "umulh	x14, x3, x14\n\t"
        "mul	x4, x3, x15\n\t"
        "adcs	x11, x11, x4\n\t"
        "umulh	x15, x3, x15\n\t"
        "mul	x4, x3, x16\n\t"
        "adcs	x12, x12, x4\n\t"
        "umulh	x16, x3, x16\n\t"
        "adc	x13, x13, xzr\n\t"
        /*  Add high product results in */
        "adds	x6, x10, x5\n\t"
        "adcs	x7, x11, x14\n\t"
        "adcs	x8, x12, x15\n\t"
        "adc	x9, x13, x16\n\t"
        "subs	x23, x23, #1\n\t"
        "b.ne	L_fe_pow22523_4_%=\n\t"
        /* Store */
        "stp	x6, x7, [x29, #48]\n\t"
        "stp	x8, x9, [x29, #64]\n\t"
        "add	x0, x29, #16\n\t"
        "add	x1, x29, #48\n\t"
        "add	x2, x29, #16\n\t"
#ifndef __APPLE__
        "bl	fe_mul\n\t"
#else
        "bl	_fe_mul\n\t"
#endif /* __APPLE__ */
        /* Loop: 50 times */
        "mov	x23, #50\n\t"
        "ldp	x6, x7, [x29, #16]\n\t"
        "ldp	x8, x9, [x29, #32]\n\t"
        "\n"
    "L_fe_pow22523_5_%=: \n\t"
        /* Square */
        /*  A[0] * A[1] */
        "umulh	x12, x6, x7\n\t"
        "mul	x11, x6, x7\n\t"
        /*  A[0] * A[3] */
        "umulh	x14, x6, x9\n\t"
        "mul	x13, x6, x9\n\t"
        /*  A[0] * A[2] */
        "mul	x3, x6, x8\n\t"
        "adds	x12, x12, x3\n\t"
        "umulh	x4, x6, x8\n\t"
        "adcs	x13, x13, x4\n\t"
        /*  A[1] * A[3] */
        "mul	x3, x7, x9\n\t"
        "adcs	x14, x14, x3\n\t"
        "umulh	x15, x7, x9\n\t"
        "adc	x15, x15, xzr\n\t"
        /*  A[1] * A[2] */
        "mul	x3, x7, x8\n\t"
        "adds	x13, x13, x3\n\t"
        "umulh	x4, x7, x8\n\t"
        "adcs	x14, x14, x4\n\t"
        /*  A[2] * A[3] */
        "mul	x3, x8, x9\n\t"
        "adcs	x15, x15, x3\n\t"
        "umulh	x16, x8, x9\n\t"
        "adc	x16, x16, xzr\n\t"
        /* Double */
        "adds	x11, x11, x11\n\t"
        "adcs	x12, x12, x12\n\t"
        "adcs	x13, x13, x13\n\t"
        "adcs	x14, x14, x14\n\t"
        "adcs	x15, x15, x15\n\t"
        "adcs	x16, x16, x16\n\t"
        "adc	x17, xzr, xzr\n\t"
        /*  A[0] * A[0] */
        "umulh	x4, x6, x6\n\t"
        "mul	x10, x6, x6\n\t"
        /*  A[1] * A[1] */
        "mul	x3, x7, x7\n\t"
        "adds	x11, x11, x4\n\t"
        "umulh	x4, x7, x7\n\t"
        "adcs	x12, x12, x3\n\t"
        /*  A[2] * A[2] */
        "mul	x3, x8, x8\n\t"
        "adcs	x13, x13, x4\n\t"
        "umulh	x4, x8, x8\n\t"
        "adcs	x14, x14, x3\n\t"
        /*  A[3] * A[3] */
        "mul	x3, x9, x9\n\t"
        "adcs	x15, x15, x4\n\t"
        "umulh	x4, x9, x9\n\t"
        "adcs	x16, x16, x3\n\t"
        "adc	x17, x17, x4\n\t"
        /* Reduce */
        "mov	x3, #38\n\t"
        "mul	x4, x3, x17\n\t"
        "adds	x13, x13, x4\n\t"
        "umulh	x5, x3, x17\n\t"
        "adc	x5, x5, xzr\n\t"
        "mov	x3, #19\n\t"
        "extr	x5, x5, x13, #63\n\t"
        "mul	x5, x5, x3\n\t"
        "and	x13, x13, #0x7fffffffffffffff\n\t"
        "mov	x3, #38\n\t"
        "mul	x4, x3, x14\n\t"
        "adds	x10, x10, x4\n\t"
        "umulh	x14, x3, x14\n\t"
        "mul	x4, x3, x15\n\t"
        "adcs	x11, x11, x4\n\t"
        "umulh	x15, x3, x15\n\t"
        "mul	x4, x3, x16\n\t"
        "adcs	x12, x12, x4\n\t"
        "umulh	x16, x3, x16\n\t"
        "adc	x13, x13, xzr\n\t"
        /*  Add high product results in */
        "adds	x6, x10, x5\n\t"
        "adcs	x7, x11, x14\n\t"
        "adcs	x8, x12, x15\n\t"
        "adc	x9, x13, x16\n\t"
        "subs	x23, x23, #1\n\t"
        "b.ne	L_fe_pow22523_5_%=\n\t"
        /* Store */
        "stp	x6, x7, [x29, #48]\n\t"
        "stp	x8, x9, [x29, #64]\n\t"
        "add	x0, x29, #48\n\t"
#ifndef NDEBUG
        "add	x1, x29, #48\n\t"
#endif /* !NDEBUG */
        "add	x2, x29, #16\n\t"
#ifndef __APPLE__
        "bl	fe_mul\n\t"
#else
        "bl	_fe_mul\n\t"
#endif /* __APPLE__ */
        /* Loop: 100 times */
        "mov	x23, #0x64\n\t"
        "ldp	x6, x7, [x29, #48]\n\t"
        "ldp	x8, x9, [x29, #64]\n\t"
        "\n"
    "L_fe_pow22523_6_%=: \n\t"
        /* Square */
        /*  A[0] * A[1] */
        "umulh	x12, x6, x7\n\t"
        "mul	x11, x6, x7\n\t"
        /*  A[0] * A[3] */
        "umulh	x14, x6, x9\n\t"
        "mul	x13, x6, x9\n\t"
        /*  A[0] * A[2] */
        "mul	x3, x6, x8\n\t"
        "adds	x12, x12, x3\n\t"
        "umulh	x4, x6, x8\n\t"
        "adcs	x13, x13, x4\n\t"
        /*  A[1] * A[3] */
        "mul	x3, x7, x9\n\t"
        "adcs	x14, x14, x3\n\t"
        "umulh	x15, x7, x9\n\t"
        "adc	x15, x15, xzr\n\t"
        /*  A[1] * A[2] */
        "mul	x3, x7, x8\n\t"
        "adds	x13, x13, x3\n\t"
        "umulh	x4, x7, x8\n\t"
        "adcs	x14, x14, x4\n\t"
        /*  A[2] * A[3] */
        "mul	x3, x8, x9\n\t"
        "adcs	x15, x15, x3\n\t"
        "umulh	x16, x8, x9\n\t"
        "adc	x16, x16, xzr\n\t"
        /* Double */
        "adds	x11, x11, x11\n\t"
        "adcs	x12, x12, x12\n\t"
        "adcs	x13, x13, x13\n\t"
        "adcs	x14, x14, x14\n\t"
        "adcs	x15, x15, x15\n\t"
        "adcs	x16, x16, x16\n\t"
        "adc	x17, xzr, xzr\n\t"
        /*  A[0] * A[0] */
        "umulh	x4, x6, x6\n\t"
        "mul	x10, x6, x6\n\t"
        /*  A[1] * A[1] */
        "mul	x3, x7, x7\n\t"
        "adds	x11, x11, x4\n\t"
        "umulh	x4, x7, x7\n\t"
        "adcs	x12, x12, x3\n\t"
        /*  A[2] * A[2] */
        "mul	x3, x8, x8\n\t"
        "adcs	x13, x13, x4\n\t"
        "umulh	x4, x8, x8\n\t"
        "adcs	x14, x14, x3\n\t"
        /*  A[3] * A[3] */
        "mul	x3, x9, x9\n\t"
        "adcs	x15, x15, x4\n\t"
        "umulh	x4, x9, x9\n\t"
        "adcs	x16, x16, x3\n\t"
        "adc	x17, x17, x4\n\t"
        /* Reduce */
        "mov	x3, #38\n\t"
        "mul	x4, x3, x17\n\t"
        "adds	x13, x13, x4\n\t"
        "umulh	x5, x3, x17\n\t"
        "adc	x5, x5, xzr\n\t"
        "mov	x3, #19\n\t"
        "extr	x5, x5, x13, #63\n\t"
        "mul	x5, x5, x3\n\t"
        "and	x13, x13, #0x7fffffffffffffff\n\t"
        "mov	x3, #38\n\t"
        "mul	x4, x3, x14\n\t"
        "adds	x10, x10, x4\n\t"
        "umulh	x14, x3, x14\n\t"
        "mul	x4, x3, x15\n\t"
        "adcs	x11, x11, x4\n\t"
        "umulh	x15, x3, x15\n\t"
        "mul	x4, x3, x16\n\t"
        "adcs	x12, x12, x4\n\t"
        "umulh	x16, x3, x16\n\t"
        "adc	x13, x13, xzr\n\t"
        /*  Add high product results in */
        "adds	x6, x10, x5\n\t"
        "adcs	x7, x11, x14\n\t"
        "adcs	x8, x12, x15\n\t"
        "adc	x9, x13, x16\n\t"
        "subs	x23, x23, #1\n\t"
        "b.ne	L_fe_pow22523_6_%=\n\t"
        /* Store */
        "stp	x6, x7, [x29, #80]\n\t"
        "stp	x8, x9, [x29, #96]\n\t"
#ifndef NDEBUG
        "add	x0, x29, #48\n\t"
#endif /* !NDEBUG */
        "add	x1, x29, #0x50\n\t"
        "add	x2, x29, #48\n\t"
#ifndef __APPLE__
        "bl	fe_mul\n\t"
#else
        "bl	_fe_mul\n\t"
#endif /* __APPLE__ */
        /* Loop: 50 times */
        "mov	x23, #50\n\t"
        "ldp	x6, x7, [x29, #48]\n\t"
        "ldp	x8, x9, [x29, #64]\n\t"
        "\n"
    "L_fe_pow22523_7_%=: \n\t"
        /* Square */
        /*  A[0] * A[1] */
        "umulh	x12, x6, x7\n\t"
        "mul	x11, x6, x7\n\t"
        /*  A[0] * A[3] */
        "umulh	x14, x6, x9\n\t"
        "mul	x13, x6, x9\n\t"
        /*  A[0] * A[2] */
        "mul	x3, x6, x8\n\t"
        "adds	x12, x12, x3\n\t"
        "umulh	x4, x6, x8\n\t"
        "adcs	x13, x13, x4\n\t"
        /*  A[1] * A[3] */
        "mul	x3, x7, x9\n\t"
        "adcs	x14, x14, x3\n\t"
        "umulh	x15, x7, x9\n\t"
        "adc	x15, x15, xzr\n\t"
        /*  A[1] * A[2] */
        "mul	x3, x7, x8\n\t"
        "adds	x13, x13, x3\n\t"
        "umulh	x4, x7, x8\n\t"
        "adcs	x14, x14, x4\n\t"
        /*  A[2] * A[3] */
        "mul	x3, x8, x9\n\t"
        "adcs	x15, x15, x3\n\t"
        "umulh	x16, x8, x9\n\t"
        "adc	x16, x16, xzr\n\t"
        /* Double */
        "adds	x11, x11, x11\n\t"
        "adcs	x12, x12, x12\n\t"
        "adcs	x13, x13, x13\n\t"
        "adcs	x14, x14, x14\n\t"
        "adcs	x15, x15, x15\n\t"
        "adcs	x16, x16, x16\n\t"
        "adc	x17, xzr, xzr\n\t"
        /*  A[0] * A[0] */
        "umulh	x4, x6, x6\n\t"
        "mul	x10, x6, x6\n\t"
        /*  A[1] * A[1] */
        "mul	x3, x7, x7\n\t"
        "adds	x11, x11, x4\n\t"
        "umulh	x4, x7, x7\n\t"
        "adcs	x12, x12, x3\n\t"
        /*  A[2] * A[2] */
        "mul	x3, x8, x8\n\t"
        "adcs	x13, x13, x4\n\t"
        "umulh	x4, x8, x8\n\t"
        "adcs	x14, x14, x3\n\t"
        /*  A[3] * A[3] */
        "mul	x3, x9, x9\n\t"
        "adcs	x15, x15, x4\n\t"
        "umulh	x4, x9, x9\n\t"
        "adcs	x16, x16, x3\n\t"
        "adc	x17, x17, x4\n\t"
        /* Reduce */
        "mov	x3, #38\n\t"
        "mul	x4, x3, x17\n\t"
        "adds	x13, x13, x4\n\t"
        "umulh	x5, x3, x17\n\t"
        "adc	x5, x5, xzr\n\t"
        "mov	x3, #19\n\t"
        "extr	x5, x5, x13, #63\n\t"
        "mul	x5, x5, x3\n\t"
        "and	x13, x13, #0x7fffffffffffffff\n\t"
        "mov	x3, #38\n\t"
        "mul	x4, x3, x14\n\t"
        "adds	x10, x10, x4\n\t"
        "umulh	x14, x3, x14\n\t"
        "mul	x4, x3, x15\n\t"
        "adcs	x11, x11, x4\n\t"
        "umulh	x15, x3, x15\n\t"
        "mul	x4, x3, x16\n\t"
        "adcs	x12, x12, x4\n\t"
        "umulh	x16, x3, x16\n\t"
        "adc	x13, x13, xzr\n\t"
        /*  Add high product results in */
        "adds	x6, x10, x5\n\t"
        "adcs	x7, x11, x14\n\t"
        "adcs	x8, x12, x15\n\t"
        "adc	x9, x13, x16\n\t"
        "subs	x23, x23, #1\n\t"
        "b.ne	L_fe_pow22523_7_%=\n\t"
        /* Store */
        "stp	x6, x7, [x29, #48]\n\t"
        "stp	x8, x9, [x29, #64]\n\t"
        "add	x0, x29, #16\n\t"
        "add	x1, x29, #48\n\t"
        "add	x2, x29, #16\n\t"
#ifndef __APPLE__
        "bl	fe_mul\n\t"
#else
        "bl	_fe_mul\n\t"
#endif /* __APPLE__ */
#ifndef NDEBUG
        "add	x0, x29, #16\n\t"
#endif /* !NDEBUG */
        "add	x1, x29, #16\n\t"
#ifndef __APPLE__
        "bl	fe_sq\n\t"
#else
        "bl	_fe_sq\n\t"
#endif /* __APPLE__ */
#ifndef __APPLE__
        "bl	fe_sq\n\t"
#else
        "bl	_fe_sq\n\t"
#endif /* __APPLE__ */
        "ldr	x0, [x29, #112]\n\t"
#ifndef NDEBUG
        "add	x1, x29, #16\n\t"
#endif /* !NDEBUG */
        "ldr	x2, [x29, #120]\n\t"
#ifndef __APPLE__
        "bl	fe_mul\n\t"
#else
        "bl	_fe_mul\n\t"
#endif /* __APPLE__ */
        "ldp	x29, x30, [sp], #0x80\n\t"
        : [r] "+r" (r)
        : [a] "r" (a)
        : "memory", "cc", "x2", "x23", "x3", "x4", "x5", "x6", "x7", "x8", "x9",
            "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17"
    );
}

void ge_p1p1_to_p2(ge_p2* r, const ge_p1p1* p)
{
    __asm__ __volatile__ (
        "stp	x29, x30, [sp, #-32]!\n\t"
        "add	x29, sp, #0\n\t"
        "str	%x[r], [x29, #16]\n\t"
        "str	%x[p], [x29, #24]\n\t"
        "mov	x2, x1\n\t"
        "add	x1, x1, #0x60\n\t"
        /* Multiply */
        "ldp	x10, x11, [x1]\n\t"
        "ldp	x12, x13, [x1, #16]\n\t"
        "ldp	x6, x7, [x2]\n\t"
        "ldp	x8, x9, [x2, #16]\n\t"
        /* A[0] * B[0] */
        "umulh	x15, x10, x6\n\t"
        "mul	x14, x10, x6\n\t"
        /* A[2] * B[0] */
        "umulh	x17, x12, x6\n\t"
        "mul	x16, x12, x6\n\t"
        /* A[1] * B[0] */
        "mul	x3, x11, x6\n\t"
        "adds	x15, x15, x3\n\t"
        "umulh	x4, x11, x6\n\t"
        "adcs	x16, x16, x4\n\t"
        /* A[1] * B[3] */
        "umulh	x20, x11, x9\n\t"
        "adc	x17, x17, xzr\n\t"
        "mul	x19, x11, x9\n\t"
        /* A[0] * B[1] */
        "mul	x3, x10, x7\n\t"
        "adds	x15, x15, x3\n\t"
        "umulh	x4, x10, x7\n\t"
        "adcs	x16, x16, x4\n\t"
        /* A[2] * B[1] */
        "mul	x3, x12, x7\n\t"
        "adcs	x17, x17, x3\n\t"
        "umulh	x4, x12, x7\n\t"
        "adcs	x19, x19, x4\n\t"
        "adc	x20, x20, xzr\n\t"
        /* A[1] * B[2] */
        "mul	x3, x11, x8\n\t"
        "adds	x17, x17, x3\n\t"
        "umulh	x4, x11, x8\n\t"
        "adcs	x19, x19, x4\n\t"
        "adcs	x20, x20, xzr\n\t"
        "adc	x21, xzr, xzr\n\t"
        /* A[0] * B[2] */
        "mul	x3, x10, x8\n\t"
        "adds	x16, x16, x3\n\t"
        "umulh	x4, x10, x8\n\t"
        "adcs	x17, x17, x4\n\t"
        "adcs	x19, x19, xzr\n\t"
        "adcs	x20, x20, xzr\n\t"
        "adc	x21, x21, xzr\n\t"
        /* A[1] * B[1] */
        "mul	x3, x11, x7\n\t"
        "adds	x16, x16, x3\n\t"
        "umulh	x4, x11, x7\n\t"
        "adcs	x17, x17, x4\n\t"
        /* A[3] * B[1] */
        "mul	x3, x13, x7\n\t"
        "adcs	x19, x19, x3\n\t"
        "umulh	x4, x13, x7\n\t"
        "adcs	x20, x20, x4\n\t"
        "adc	x21, x21, xzr\n\t"
        /* A[2] * B[2] */
        "mul	x3, x12, x8\n\t"
        "adds	x19, x19, x3\n\t"
        "umulh	x4, x12, x8\n\t"
        "adcs	x20, x20, x4\n\t"
        /* A[3] * B[3] */
        "mul	x3, x13, x9\n\t"
        "adcs	x21, x21, x3\n\t"
        "umulh	x22, x13, x9\n\t"
        "adc	x22, x22, xzr\n\t"
        /* A[0] * B[3] */
        "mul	x3, x10, x9\n\t"
        "adds	x17, x17, x3\n\t"
        "umulh	x4, x10, x9\n\t"
        "adcs	x19, x19, x4\n\t"
        /* A[2] * B[3] */
        "mul	x3, x12, x9\n\t"
        "adcs	x20, x20, x3\n\t"
        "umulh	x4, x12, x9\n\t"
        "adcs	x21, x21, x4\n\t"
        "adc	x22, x22, xzr\n\t"
        /* A[3] * B[0] */
        "mul	x3, x13, x6\n\t"
        "adds	x17, x17, x3\n\t"
        "umulh	x4, x13, x6\n\t"
        "adcs	x19, x19, x4\n\t"
        /* A[3] * B[2] */
        "mul	x3, x13, x8\n\t"
        "adcs	x20, x20, x3\n\t"
        "umulh	x4, x13, x8\n\t"
        "adcs	x21, x21, x4\n\t"
        "adc	x22, x22, xzr\n\t"
        /* Reduce */
        "mov	x3, #38\n\t"
        "mul	x4, x3, x22\n\t"
        "adds	x17, x17, x4\n\t"
        "umulh	x5, x3, x22\n\t"
        "adc	x5, x5, xzr\n\t"
        "mov	x3, #19\n\t"
        "extr	x5, x5, x17, #63\n\t"
        "mul	x5, x5, x3\n\t"
        "and	x17, x17, #0x7fffffffffffffff\n\t"
        "mov	x3, #38\n\t"
        "mul	x4, x3, x19\n\t"
        "adds	x14, x14, x4\n\t"
        "umulh	x19, x3, x19\n\t"
        "mul	x4, x3, x20\n\t"
        "adcs	x15, x15, x4\n\t"
        "umulh	x20, x3, x20\n\t"
        "mul	x4, x3, x21\n\t"
        "adcs	x16, x16, x4\n\t"
        "umulh	x21, x3, x21\n\t"
        "adc	x17, x17, xzr\n\t"
        /*  Add high product results in */
        "adds	x14, x14, x5\n\t"
        "adcs	x15, x15, x19\n\t"
        "adcs	x16, x16, x20\n\t"
        "adc	x17, x17, x21\n\t"
        /* Store */
        "stp	x14, x15, [x0]\n\t"
        "stp	x16, x17, [x0, #16]\n\t"
        "sub	x2, x1, #32\n\t"
        "add	x0, x0, #0x40\n\t"
        /* Multiply */
        "ldp	x6, x7, [x2]\n\t"
        "ldp	x8, x9, [x2, #16]\n\t"
        /* A[0] * B[0] */
        "umulh	x15, x10, x6\n\t"
        "mul	x14, x10, x6\n\t"
        /* A[2] * B[0] */
        "umulh	x17, x12, x6\n\t"
        "mul	x16, x12, x6\n\t"
        /* A[1] * B[0] */
        "mul	x3, x11, x6\n\t"
        "adds	x15, x15, x3\n\t"
        "umulh	x4, x11, x6\n\t"
        "adcs	x16, x16, x4\n\t"
        /* A[1] * B[3] */
        "umulh	x20, x11, x9\n\t"
        "adc	x17, x17, xzr\n\t"
        "mul	x19, x11, x9\n\t"
        /* A[0] * B[1] */
        "mul	x3, x10, x7\n\t"
        "adds	x15, x15, x3\n\t"
        "umulh	x4, x10, x7\n\t"
        "adcs	x16, x16, x4\n\t"
        /* A[2] * B[1] */
        "mul	x3, x12, x7\n\t"
        "adcs	x17, x17, x3\n\t"
        "umulh	x4, x12, x7\n\t"
        "adcs	x19, x19, x4\n\t"
        "adc	x20, x20, xzr\n\t"
        /* A[1] * B[2] */
        "mul	x3, x11, x8\n\t"
        "adds	x17, x17, x3\n\t"
        "umulh	x4, x11, x8\n\t"
        "adcs	x19, x19, x4\n\t"
        "adcs	x20, x20, xzr\n\t"
        "adc	x21, xzr, xzr\n\t"
        /* A[0] * B[2] */
        "mul	x3, x10, x8\n\t"
        "adds	x16, x16, x3\n\t"
        "umulh	x4, x10, x8\n\t"
        "adcs	x17, x17, x4\n\t"
        "adcs	x19, x19, xzr\n\t"
        "adcs	x20, x20, xzr\n\t"
        "adc	x21, x21, xzr\n\t"
        /* A[1] * B[1] */
        "mul	x3, x11, x7\n\t"
        "adds	x16, x16, x3\n\t"
        "umulh	x4, x11, x7\n\t"
        "adcs	x17, x17, x4\n\t"
        /* A[3] * B[1] */
        "mul	x3, x13, x7\n\t"
        "adcs	x19, x19, x3\n\t"
        "umulh	x4, x13, x7\n\t"
        "adcs	x20, x20, x4\n\t"
        "adc	x21, x21, xzr\n\t"
        /* A[2] * B[2] */
        "mul	x3, x12, x8\n\t"
        "adds	x19, x19, x3\n\t"
        "umulh	x4, x12, x8\n\t"
        "adcs	x20, x20, x4\n\t"
        /* A[3] * B[3] */
        "mul	x3, x13, x9\n\t"
        "adcs	x21, x21, x3\n\t"
        "umulh	x22, x13, x9\n\t"
        "adc	x22, x22, xzr\n\t"
        /* A[0] * B[3] */
        "mul	x3, x10, x9\n\t"
        "adds	x17, x17, x3\n\t"
        "umulh	x4, x10, x9\n\t"
        "adcs	x19, x19, x4\n\t"
        /* A[2] * B[3] */
        "mul	x3, x12, x9\n\t"
        "adcs	x20, x20, x3\n\t"
        "umulh	x4, x12, x9\n\t"
        "adcs	x21, x21, x4\n\t"
        "adc	x22, x22, xzr\n\t"
        /* A[3] * B[0] */
        "mul	x3, x13, x6\n\t"
        "adds	x17, x17, x3\n\t"
        "umulh	x4, x13, x6\n\t"
        "adcs	x19, x19, x4\n\t"
        /* A[3] * B[2] */
        "mul	x3, x13, x8\n\t"
        "adcs	x20, x20, x3\n\t"
        "umulh	x4, x13, x8\n\t"
        "adcs	x21, x21, x4\n\t"
        "adc	x22, x22, xzr\n\t"
        /* Reduce */
        "mov	x3, #38\n\t"
        "mul	x4, x3, x22\n\t"
        "adds	x17, x17, x4\n\t"
        "umulh	x5, x3, x22\n\t"
        "adc	x5, x5, xzr\n\t"
        "mov	x3, #19\n\t"
        "extr	x5, x5, x17, #63\n\t"
        "mul	x5, x5, x3\n\t"
        "and	x17, x17, #0x7fffffffffffffff\n\t"
        "mov	x3, #38\n\t"
        "mul	x4, x3, x19\n\t"
        "adds	x14, x14, x4\n\t"
        "umulh	x19, x3, x19\n\t"
        "mul	x4, x3, x20\n\t"
        "adcs	x15, x15, x4\n\t"
        "umulh	x20, x3, x20\n\t"
        "mul	x4, x3, x21\n\t"
        "adcs	x16, x16, x4\n\t"
        "umulh	x21, x3, x21\n\t"
        "adc	x17, x17, xzr\n\t"
        /*  Add high product results in */
        "adds	x14, x14, x5\n\t"
        "adcs	x15, x15, x19\n\t"
        "adcs	x16, x16, x20\n\t"
        "adc	x17, x17, x21\n\t"
        /* Store */
        "stp	x14, x15, [x0]\n\t"
        "stp	x16, x17, [x0, #16]\n\t"
        "sub	x1, x1, #0x40\n\t"
        "sub	x0, x0, #32\n\t"
        /* Multiply */
        "ldp	x10, x11, [x1]\n\t"
        "ldp	x12, x13, [x1, #16]\n\t"
        /* A[0] * B[0] */
        "umulh	x15, x10, x6\n\t"
        "mul	x14, x10, x6\n\t"
        /* A[2] * B[0] */
        "umulh	x17, x12, x6\n\t"
        "mul	x16, x12, x6\n\t"
        /* A[1] * B[0] */
        "mul	x3, x11, x6\n\t"
        "adds	x15, x15, x3\n\t"
        "umulh	x4, x11, x6\n\t"
        "adcs	x16, x16, x4\n\t"
        /* A[1] * B[3] */
        "umulh	x20, x11, x9\n\t"
        "adc	x17, x17, xzr\n\t"
        "mul	x19, x11, x9\n\t"
        /* A[0] * B[1] */
        "mul	x3, x10, x7\n\t"
        "adds	x15, x15, x3\n\t"
        "umulh	x4, x10, x7\n\t"
        "adcs	x16, x16, x4\n\t"
        /* A[2] * B[1] */
        "mul	x3, x12, x7\n\t"
        "adcs	x17, x17, x3\n\t"
        "umulh	x4, x12, x7\n\t"
        "adcs	x19, x19, x4\n\t"
        "adc	x20, x20, xzr\n\t"
        /* A[1] * B[2] */
        "mul	x3, x11, x8\n\t"
        "adds	x17, x17, x3\n\t"
        "umulh	x4, x11, x8\n\t"
        "adcs	x19, x19, x4\n\t"
        "adcs	x20, x20, xzr\n\t"
        "adc	x21, xzr, xzr\n\t"
        /* A[0] * B[2] */
        "mul	x3, x10, x8\n\t"
        "adds	x16, x16, x3\n\t"
        "umulh	x4, x10, x8\n\t"
        "adcs	x17, x17, x4\n\t"
        "adcs	x19, x19, xzr\n\t"
        "adcs	x20, x20, xzr\n\t"
        "adc	x21, x21, xzr\n\t"
        /* A[1] * B[1] */
        "mul	x3, x11, x7\n\t"
        "adds	x16, x16, x3\n\t"
        "umulh	x4, x11, x7\n\t"
        "adcs	x17, x17, x4\n\t"
        /* A[3] * B[1] */
        "mul	x3, x13, x7\n\t"
        "adcs	x19, x19, x3\n\t"
        "umulh	x4, x13, x7\n\t"
        "adcs	x20, x20, x4\n\t"
        "adc	x21, x21, xzr\n\t"
        /* A[2] * B[2] */
        "mul	x3, x12, x8\n\t"
        "adds	x19, x19, x3\n\t"
        "umulh	x4, x12, x8\n\t"
        "adcs	x20, x20, x4\n\t"
        /* A[3] * B[3] */
        "mul	x3, x13, x9\n\t"
        "adcs	x21, x21, x3\n\t"
        "umulh	x22, x13, x9\n\t"
        "adc	x22, x22, xzr\n\t"
        /* A[0] * B[3] */
        "mul	x3, x10, x9\n\t"
        "adds	x17, x17, x3\n\t"
        "umulh	x4, x10, x9\n\t"
        "adcs	x19, x19, x4\n\t"
        /* A[2] * B[3] */
        "mul	x3, x12, x9\n\t"
        "adcs	x20, x20, x3\n\t"
        "umulh	x4, x12, x9\n\t"
        "adcs	x21, x21, x4\n\t"
        "adc	x22, x22, xzr\n\t"
        /* A[3] * B[0] */
        "mul	x3, x13, x6\n\t"
        "adds	x17, x17, x3\n\t"
        "umulh	x4, x13, x6\n\t"
        "adcs	x19, x19, x4\n\t"
        /* A[3] * B[2] */
        "mul	x3, x13, x8\n\t"
        "adcs	x20, x20, x3\n\t"
        "umulh	x4, x13, x8\n\t"
        "adcs	x21, x21, x4\n\t"
        "adc	x22, x22, xzr\n\t"
        /* Reduce */
        "mov	x3, #38\n\t"
        "mul	x4, x3, x22\n\t"
        "adds	x17, x17, x4\n\t"
        "umulh	x5, x3, x22\n\t"
        "adc	x5, x5, xzr\n\t"
        "mov	x3, #19\n\t"
        "extr	x5, x5, x17, #63\n\t"
        "mul	x5, x5, x3\n\t"
        "and	x17, x17, #0x7fffffffffffffff\n\t"
        "mov	x3, #38\n\t"
        "mul	x4, x3, x19\n\t"
        "adds	x14, x14, x4\n\t"
        "umulh	x19, x3, x19\n\t"
        "mul	x4, x3, x20\n\t"
        "adcs	x15, x15, x4\n\t"
        "umulh	x20, x3, x20\n\t"
        "mul	x4, x3, x21\n\t"
        "adcs	x16, x16, x4\n\t"
        "umulh	x21, x3, x21\n\t"
        "adc	x17, x17, xzr\n\t"
        /*  Add high product results in */
        "adds	x14, x14, x5\n\t"
        "adcs	x15, x15, x19\n\t"
        "adcs	x16, x16, x20\n\t"
        "adc	x17, x17, x21\n\t"
        /* Store */
        "stp	x14, x15, [x0]\n\t"
        "stp	x16, x17, [x0, #16]\n\t"
        "ldp	x29, x30, [sp], #32\n\t"
        : [r] "+r" (r)
        : [p] "r" (p)
        : "memory", "cc", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10",
            "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20",
            "x21", "x22"
    );
}

void ge_p1p1_to_p3(ge_p3* r, const ge_p1p1* p)
{
    __asm__ __volatile__ (
        "stp	x29, x30, [sp, #-32]!\n\t"
        "add	x29, sp, #0\n\t"
        "str	%x[r], [x29, #16]\n\t"
        "str	%x[p], [x29, #24]\n\t"
        "mov	x2, x1\n\t"
        "add	x1, x1, #0x60\n\t"
        /* Multiply */
        "ldp	x10, x11, [x1]\n\t"
        "ldp	x12, x13, [x1, #16]\n\t"
        "ldp	x6, x7, [x2]\n\t"
        "ldp	x8, x9, [x2, #16]\n\t"
        /* A[0] * B[0] */
        "umulh	x15, x10, x6\n\t"
        "mul	x14, x10, x6\n\t"
        /* A[2] * B[0] */
        "umulh	x17, x12, x6\n\t"
        "mul	x16, x12, x6\n\t"
        /* A[1] * B[0] */
        "mul	x3, x11, x6\n\t"
        "adds	x15, x15, x3\n\t"
        "umulh	x4, x11, x6\n\t"
        "adcs	x16, x16, x4\n\t"
        /* A[1] * B[3] */
        "umulh	x20, x11, x9\n\t"
        "adc	x17, x17, xzr\n\t"
        "mul	x19, x11, x9\n\t"
        /* A[0] * B[1] */
        "mul	x3, x10, x7\n\t"
        "adds	x15, x15, x3\n\t"
        "umulh	x4, x10, x7\n\t"
        "adcs	x16, x16, x4\n\t"
        /* A[2] * B[1] */
        "mul	x3, x12, x7\n\t"
        "adcs	x17, x17, x3\n\t"
        "umulh	x4, x12, x7\n\t"
        "adcs	x19, x19, x4\n\t"
        "adc	x20, x20, xzr\n\t"
        /* A[1] * B[2] */
        "mul	x3, x11, x8\n\t"
        "adds	x17, x17, x3\n\t"
        "umulh	x4, x11, x8\n\t"
        "adcs	x19, x19, x4\n\t"
        "adcs	x20, x20, xzr\n\t"
        "adc	x21, xzr, xzr\n\t"
        /* A[0] * B[2] */
        "mul	x3, x10, x8\n\t"
        "adds	x16, x16, x3\n\t"
        "umulh	x4, x10, x8\n\t"
        "adcs	x17, x17, x4\n\t"
        "adcs	x19, x19, xzr\n\t"
        "adcs	x20, x20, xzr\n\t"
        "adc	x21, x21, xzr\n\t"
        /* A[1] * B[1] */
        "mul	x3, x11, x7\n\t"
        "adds	x16, x16, x3\n\t"
        "umulh	x4, x11, x7\n\t"
        "adcs	x17, x17, x4\n\t"
        /* A[3] * B[1] */
        "mul	x3, x13, x7\n\t"
        "adcs	x19, x19, x3\n\t"
        "umulh	x4, x13, x7\n\t"
        "adcs	x20, x20, x4\n\t"
        "adc	x21, x21, xzr\n\t"
        /* A[2] * B[2] */
        "mul	x3, x12, x8\n\t"
        "adds	x19, x19, x3\n\t"
        "umulh	x4, x12, x8\n\t"
        "adcs	x20, x20, x4\n\t"
        /* A[3] * B[3] */
        "mul	x3, x13, x9\n\t"
        "adcs	x21, x21, x3\n\t"
        "umulh	x22, x13, x9\n\t"
        "adc	x22, x22, xzr\n\t"
        /* A[0] * B[3] */
        "mul	x3, x10, x9\n\t"
        "adds	x17, x17, x3\n\t"
        "umulh	x4, x10, x9\n\t"
        "adcs	x19, x19, x4\n\t"
        /* A[2] * B[3] */
        "mul	x3, x12, x9\n\t"
        "adcs	x20, x20, x3\n\t"
        "umulh	x4, x12, x9\n\t"
        "adcs	x21, x21, x4\n\t"
        "adc	x22, x22, xzr\n\t"
        /* A[3] * B[0] */
        "mul	x3, x13, x6\n\t"
        "adds	x17, x17, x3\n\t"
        "umulh	x4, x13, x6\n\t"
        "adcs	x19, x19, x4\n\t"
        /* A[3] * B[2] */
        "mul	x3, x13, x8\n\t"
        "adcs	x20, x20, x3\n\t"
        "umulh	x4, x13, x8\n\t"
        "adcs	x21, x21, x4\n\t"
        "adc	x22, x22, xzr\n\t"
        /* Reduce */
        "mov	x3, #38\n\t"
        "mul	x4, x3, x22\n\t"
        "adds	x17, x17, x4\n\t"
        "umulh	x5, x3, x22\n\t"
        "adc	x5, x5, xzr\n\t"
        "mov	x3, #19\n\t"
        "extr	x5, x5, x17, #63\n\t"
        "mul	x5, x5, x3\n\t"
        "and	x17, x17, #0x7fffffffffffffff\n\t"
        "mov	x3, #38\n\t"
        "mul	x4, x3, x19\n\t"
        "adds	x14, x14, x4\n\t"
        "umulh	x19, x3, x19\n\t"
        "mul	x4, x3, x20\n\t"
        "adcs	x15, x15, x4\n\t"
        "umulh	x20, x3, x20\n\t"
        "mul	x4, x3, x21\n\t"
        "adcs	x16, x16, x4\n\t"
        "umulh	x21, x3, x21\n\t"
        "adc	x17, x17, xzr\n\t"
        /*  Add high product results in */
        "adds	x14, x14, x5\n\t"
        "adcs	x15, x15, x19\n\t"
        "adcs	x16, x16, x20\n\t"
        "adc	x17, x17, x21\n\t"
        /* Store */
        "stp	x14, x15, [x0]\n\t"
        "stp	x16, x17, [x0, #16]\n\t"
        "sub	x1, x1, #0x40\n\t"
        "add	x0, x0, #0x60\n\t"
        /* Multiply */
        "ldp	x23, x24, [x1]\n\t"
        "ldp	x25, x26, [x1, #16]\n\t"
        /* A[0] * B[0] */
        "umulh	x15, x23, x6\n\t"
        "mul	x14, x23, x6\n\t"
        /* A[2] * B[0] */
        "umulh	x17, x25, x6\n\t"
        "mul	x16, x25, x6\n\t"
        /* A[1] * B[0] */
        "mul	x3, x24, x6\n\t"
        "adds	x15, x15, x3\n\t"
        "umulh	x4, x24, x6\n\t"
        "adcs	x16, x16, x4\n\t"
        /* A[1] * B[3] */
        "umulh	x20, x24, x9\n\t"
        "adc	x17, x17, xzr\n\t"
        "mul	x19, x24, x9\n\t"
        /* A[0] * B[1] */
        "mul	x3, x23, x7\n\t"
        "adds	x15, x15, x3\n\t"
        "umulh	x4, x23, x7\n\t"
        "adcs	x16, x16, x4\n\t"
        /* A[2] * B[1] */
        "mul	x3, x25, x7\n\t"
        "adcs	x17, x17, x3\n\t"
        "umulh	x4, x25, x7\n\t"
        "adcs	x19, x19, x4\n\t"
        "adc	x20, x20, xzr\n\t"
        /* A[1] * B[2] */
        "mul	x3, x24, x8\n\t"
        "adds	x17, x17, x3\n\t"
        "umulh	x4, x24, x8\n\t"
        "adcs	x19, x19, x4\n\t"
        "adcs	x20, x20, xzr\n\t"
        "adc	x21, xzr, xzr\n\t"
        /* A[0] * B[2] */
        "mul	x3, x23, x8\n\t"
        "adds	x16, x16, x3\n\t"
        "umulh	x4, x23, x8\n\t"
        "adcs	x17, x17, x4\n\t"
        "adcs	x19, x19, xzr\n\t"
        "adcs	x20, x20, xzr\n\t"
        "adc	x21, x21, xzr\n\t"
        /* A[1] * B[1] */
        "mul	x3, x24, x7\n\t"
        "adds	x16, x16, x3\n\t"
        "umulh	x4, x24, x7\n\t"
        "adcs	x17, x17, x4\n\t"
        /* A[3] * B[1] */
        "mul	x3, x26, x7\n\t"
        "adcs	x19, x19, x3\n\t"
        "umulh	x4, x26, x7\n\t"
        "adcs	x20, x20, x4\n\t"
        "adc	x21, x21, xzr\n\t"
        /* A[2] * B[2] */
        "mul	x3, x25, x8\n\t"
        "adds	x19, x19, x3\n\t"
        "umulh	x4, x25, x8\n\t"
        "adcs	x20, x20, x4\n\t"
        /* A[3] * B[3] */
        "mul	x3, x26, x9\n\t"
        "adcs	x21, x21, x3\n\t"
        "umulh	x22, x26, x9\n\t"
        "adc	x22, x22, xzr\n\t"
        /* A[0] * B[3] */
        "mul	x3, x23, x9\n\t"
        "adds	x17, x17, x3\n\t"
        "umulh	x4, x23, x9\n\t"
        "adcs	x19, x19, x4\n\t"
        /* A[2] * B[3] */
        "mul	x3, x25, x9\n\t"
        "adcs	x20, x20, x3\n\t"
        "umulh	x4, x25, x9\n\t"
        "adcs	x21, x21, x4\n\t"
        "adc	x22, x22, xzr\n\t"
        /* A[3] * B[0] */
        "mul	x3, x26, x6\n\t"
        "adds	x17, x17, x3\n\t"
        "umulh	x4, x26, x6\n\t"
        "adcs	x19, x19, x4\n\t"
        /* A[3] * B[2] */
        "mul	x3, x26, x8\n\t"
        "adcs	x20, x20, x3\n\t"
        "umulh	x4, x26, x8\n\t"
        "adcs	x21, x21, x4\n\t"
        "adc	x22, x22, xzr\n\t"
        /* Reduce */
        "mov	x3, #38\n\t"
        "mul	x4, x3, x22\n\t"
        "adds	x17, x17, x4\n\t"
        "umulh	x5, x3, x22\n\t"
        "adc	x5, x5, xzr\n\t"
        "mov	x3, #19\n\t"
        "extr	x5, x5, x17, #63\n\t"
        "mul	x5, x5, x3\n\t"
        "and	x17, x17, #0x7fffffffffffffff\n\t"
        "mov	x3, #38\n\t"
        "mul	x4, x3, x19\n\t"
        "adds	x14, x14, x4\n\t"
        "umulh	x19, x3, x19\n\t"
        "mul	x4, x3, x20\n\t"
        "adcs	x15, x15, x4\n\t"
        "umulh	x20, x3, x20\n\t"
        "mul	x4, x3, x21\n\t"
        "adcs	x16, x16, x4\n\t"
        "umulh	x21, x3, x21\n\t"
        "adc	x17, x17, xzr\n\t"
        /*  Add high product results in */
        "adds	x14, x14, x5\n\t"
        "adcs	x15, x15, x19\n\t"
        "adcs	x16, x16, x20\n\t"
        "adc	x17, x17, x21\n\t"
        /* Store */
        "stp	x14, x15, [x0]\n\t"
        "stp	x16, x17, [x0, #16]\n\t"
        "add	x2, x1, #32\n\t"
        "sub	x0, x0, #0x40\n\t"
        /* Multiply */
        "ldp	x6, x7, [x2]\n\t"
        "ldp	x8, x9, [x2, #16]\n\t"
        /* A[0] * B[0] */
        "umulh	x15, x23, x6\n\t"
        "mul	x14, x23, x6\n\t"
        /* A[2] * B[0] */
        "umulh	x17, x25, x6\n\t"
        "mul	x16, x25, x6\n\t"
        /* A[1] * B[0] */
        "mul	x3, x24, x6\n\t"
        "adds	x15, x15, x3\n\t"
        "umulh	x4, x24, x6\n\t"
        "adcs	x16, x16, x4\n\t"
        /* A[1] * B[3] */
        "umulh	x20, x24, x9\n\t"
        "adc	x17, x17, xzr\n\t"
        "mul	x19, x24, x9\n\t"
        /* A[0] * B[1] */
        "mul	x3, x23, x7\n\t"
        "adds	x15, x15, x3\n\t"
        "umulh	x4, x23, x7\n\t"
        "adcs	x16, x16, x4\n\t"
        /* A[2] * B[1] */
        "mul	x3, x25, x7\n\t"
        "adcs	x17, x17, x3\n\t"
        "umulh	x4, x25, x7\n\t"
        "adcs	x19, x19, x4\n\t"
        "adc	x20, x20, xzr\n\t"
        /* A[1] * B[2] */
        "mul	x3, x24, x8\n\t"
        "adds	x17, x17, x3\n\t"
        "umulh	x4, x24, x8\n\t"
        "adcs	x19, x19, x4\n\t"
        "adcs	x20, x20, xzr\n\t"
        "adc	x21, xzr, xzr\n\t"
        /* A[0] * B[2] */
        "mul	x3, x23, x8\n\t"
        "adds	x16, x16, x3\n\t"
        "umulh	x4, x23, x8\n\t"
        "adcs	x17, x17, x4\n\t"
        "adcs	x19, x19, xzr\n\t"
        "adcs	x20, x20, xzr\n\t"
        "adc	x21, x21, xzr\n\t"
        /* A[1] * B[1] */
        "mul	x3, x24, x7\n\t"
        "adds	x16, x16, x3\n\t"
        "umulh	x4, x24, x7\n\t"
        "adcs	x17, x17, x4\n\t"
        /* A[3] * B[1] */
        "mul	x3, x26, x7\n\t"
        "adcs	x19, x19, x3\n\t"
        "umulh	x4, x26, x7\n\t"
        "adcs	x20, x20, x4\n\t"
        "adc	x21, x21, xzr\n\t"
        /* A[2] * B[2] */
        "mul	x3, x25, x8\n\t"
        "adds	x19, x19, x3\n\t"
        "umulh	x4, x25, x8\n\t"
        "adcs	x20, x20, x4\n\t"
        /* A[3] * B[3] */
        "mul	x3, x26, x9\n\t"
        "adcs	x21, x21, x3\n\t"
        "umulh	x22, x26, x9\n\t"
        "adc	x22, x22, xzr\n\t"
        /* A[0] * B[3] */
        "mul	x3, x23, x9\n\t"
        "adds	x17, x17, x3\n\t"
        "umulh	x4, x23, x9\n\t"
        "adcs	x19, x19, x4\n\t"
        /* A[2] * B[3] */
        "mul	x3, x25, x9\n\t"
        "adcs	x20, x20, x3\n\t"
        "umulh	x4, x25, x9\n\t"
        "adcs	x21, x21, x4\n\t"
        "adc	x22, x22, xzr\n\t"
        /* A[3] * B[0] */
        "mul	x3, x26, x6\n\t"
        "adds	x17, x17, x3\n\t"
        "umulh	x4, x26, x6\n\t"
        "adcs	x19, x19, x4\n\t"
        /* A[3] * B[2] */
        "mul	x3, x26, x8\n\t"
        "adcs	x20, x20, x3\n\t"
        "umulh	x4, x26, x8\n\t"
        "adcs	x21, x21, x4\n\t"
        "adc	x22, x22, xzr\n\t"
        /* Reduce */
        "mov	x3, #38\n\t"
        "mul	x4, x3, x22\n\t"
        "adds	x17, x17, x4\n\t"
        "umulh	x5, x3, x22\n\t"
        "adc	x5, x5, xzr\n\t"
        "mov	x3, #19\n\t"
        "extr	x5, x5, x17, #63\n\t"
        "mul	x5, x5, x3\n\t"
        "and	x17, x17, #0x7fffffffffffffff\n\t"
        "mov	x3, #38\n\t"
        "mul	x4, x3, x19\n\t"
        "adds	x14, x14, x4\n\t"
        "umulh	x19, x3, x19\n\t"
        "mul	x4, x3, x20\n\t"
        "adcs	x15, x15, x4\n\t"
        "umulh	x20, x3, x20\n\t"
        "mul	x4, x3, x21\n\t"
        "adcs	x16, x16, x4\n\t"
        "umulh	x21, x3, x21\n\t"
        "adc	x17, x17, xzr\n\t"
        /*  Add high product results in */
        "adds	x14, x14, x5\n\t"
        "adcs	x15, x15, x19\n\t"
        "adcs	x16, x16, x20\n\t"
        "adc	x17, x17, x21\n\t"
        /* Store */
        "stp	x14, x15, [x0]\n\t"
        "stp	x16, x17, [x0, #16]\n\t"
        "add	x1, x1, #0x40\n\t"
        "add	x0, x0, #32\n\t"
        /* Multiply */
        /* A[0] * B[0] */
        "umulh	x15, x10, x6\n\t"
        "mul	x14, x10, x6\n\t"
        /* A[2] * B[0] */
        "umulh	x17, x12, x6\n\t"
        "mul	x16, x12, x6\n\t"
        /* A[1] * B[0] */
        "mul	x3, x11, x6\n\t"
        "adds	x15, x15, x3\n\t"
        "umulh	x4, x11, x6\n\t"
        "adcs	x16, x16, x4\n\t"
        /* A[1] * B[3] */
        "umulh	x20, x11, x9\n\t"
        "adc	x17, x17, xzr\n\t"
        "mul	x19, x11, x9\n\t"
        /* A[0] * B[1] */
        "mul	x3, x10, x7\n\t"
        "adds	x15, x15, x3\n\t"
        "umulh	x4, x10, x7\n\t"
        "adcs	x16, x16, x4\n\t"
        /* A[2] * B[1] */
        "mul	x3, x12, x7\n\t"
        "adcs	x17, x17, x3\n\t"
        "umulh	x4, x12, x7\n\t"
        "adcs	x19, x19, x4\n\t"
        "adc	x20, x20, xzr\n\t"
        /* A[1] * B[2] */
        "mul	x3, x11, x8\n\t"
        "adds	x17, x17, x3\n\t"
        "umulh	x4, x11, x8\n\t"
        "adcs	x19, x19, x4\n\t"
        "adcs	x20, x20, xzr\n\t"
        "adc	x21, xzr, xzr\n\t"
        /* A[0] * B[2] */
        "mul	x3, x10, x8\n\t"
        "adds	x16, x16, x3\n\t"
        "umulh	x4, x10, x8\n\t"
        "adcs	x17, x17, x4\n\t"
        "adcs	x19, x19, xzr\n\t"
        "adcs	x20, x20, xzr\n\t"
        "adc	x21, x21, xzr\n\t"
        /* A[1] * B[1] */
        "mul	x3, x11, x7\n\t"
        "adds	x16, x16, x3\n\t"
        "umulh	x4, x11, x7\n\t"
        "adcs	x17, x17, x4\n\t"
        /* A[3] * B[1] */
        "mul	x3, x13, x7\n\t"
        "adcs	x19, x19, x3\n\t"
        "umulh	x4, x13, x7\n\t"
        "adcs	x20, x20, x4\n\t"
        "adc	x21, x21, xzr\n\t"
        /* A[2] * B[2] */
        "mul	x3, x12, x8\n\t"
        "adds	x19, x19, x3\n\t"
        "umulh	x4, x12, x8\n\t"
        "adcs	x20, x20, x4\n\t"
        /* A[3] * B[3] */
        "mul	x3, x13, x9\n\t"
        "adcs	x21, x21, x3\n\t"
        "umulh	x22, x13, x9\n\t"
        "adc	x22, x22, xzr\n\t"
        /* A[0] * B[3] */
        "mul	x3, x10, x9\n\t"
        "adds	x17, x17, x3\n\t"
        "umulh	x4, x10, x9\n\t"
        "adcs	x19, x19, x4\n\t"
        /* A[2] * B[3] */
        "mul	x3, x12, x9\n\t"
        "adcs	x20, x20, x3\n\t"
        "umulh	x4, x12, x9\n\t"
        "adcs	x21, x21, x4\n\t"
        "adc	x22, x22, xzr\n\t"
        /* A[3] * B[0] */
        "mul	x3, x13, x6\n\t"
        "adds	x17, x17, x3\n\t"
        "umulh	x4, x13, x6\n\t"
        "adcs	x19, x19, x4\n\t"
        /* A[3] * B[2] */
        "mul	x3, x13, x8\n\t"
        "adcs	x20, x20, x3\n\t"
        "umulh	x4, x13, x8\n\t"
        "adcs	x21, x21, x4\n\t"
        "adc	x22, x22, xzr\n\t"
        /* Reduce */
        "mov	x3, #38\n\t"
        "mul	x4, x3, x22\n\t"
        "adds	x17, x17, x4\n\t"
        "umulh	x5, x3, x22\n\t"
        "adc	x5, x5, xzr\n\t"
        "mov	x3, #19\n\t"
        "extr	x5, x5, x17, #63\n\t"
        "mul	x5, x5, x3\n\t"
        "and	x17, x17, #0x7fffffffffffffff\n\t"
        "mov	x3, #38\n\t"
        "mul	x4, x3, x19\n\t"
        "adds	x14, x14, x4\n\t"
        "umulh	x19, x3, x19\n\t"
        "mul	x4, x3, x20\n\t"
        "adcs	x15, x15, x4\n\t"
        "umulh	x20, x3, x20\n\t"
        "mul	x4, x3, x21\n\t"
        "adcs	x16, x16, x4\n\t"
        "umulh	x21, x3, x21\n\t"
        "adc	x17, x17, xzr\n\t"
        /*  Add high product results in */
        "adds	x14, x14, x5\n\t"
        "adcs	x15, x15, x19\n\t"
        "adcs	x16, x16, x20\n\t"
        "adc	x17, x17, x21\n\t"
        /* Store */
        "stp	x14, x15, [x0]\n\t"
        "stp	x16, x17, [x0, #16]\n\t"
        "ldp	x29, x30, [sp], #32\n\t"
        : [r] "+r" (r)
        : [p] "r" (p)
        : "memory", "cc", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10",
            "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20",
            "x21", "x22", "x23", "x24", "x25", "x26"
    );
}

void ge_p2_dbl(ge_p1p1* r, const ge_p2* p)
{
    __asm__ __volatile__ (
        "stp	x29, x30, [sp, #-32]!\n\t"
        "add	x29, sp, #0\n\t"
        "str	%x[r], [x29, #16]\n\t"
        "str	%x[p], [x29, #24]\n\t"
        "add	x0, x0, #0x40\n\t"
        /* Square */
        "ldp	x4, x5, [x1]\n\t"
        "ldp	x6, x7, [x1, #16]\n\t"
        /*  A[0] * A[1] */
        "umulh	x10, x4, x5\n\t"
        "mul	x9, x4, x5\n\t"
        /*  A[0] * A[3] */
        "umulh	x12, x4, x7\n\t"
        "mul	x11, x4, x7\n\t"
        /*  A[0] * A[2] */
        "mul	x25, x4, x6\n\t"
        "adds	x10, x10, x25\n\t"
        "umulh	x26, x4, x6\n\t"
        "adcs	x11, x11, x26\n\t"
        /*  A[1] * A[3] */
        "mul	x25, x5, x7\n\t"
        "adcs	x12, x12, x25\n\t"
        "umulh	x13, x5, x7\n\t"
        "adc	x13, x13, xzr\n\t"
        /*  A[1] * A[2] */
        "mul	x25, x5, x6\n\t"
        "adds	x11, x11, x25\n\t"
        "umulh	x26, x5, x6\n\t"
        "adcs	x12, x12, x26\n\t"
        /*  A[2] * A[3] */
        "mul	x25, x6, x7\n\t"
        "adcs	x13, x13, x25\n\t"
        "umulh	x14, x6, x7\n\t"
        "adc	x14, x14, xzr\n\t"
        /* Double */
        "adds	x9, x9, x9\n\t"
        "adcs	x10, x10, x10\n\t"
        "adcs	x11, x11, x11\n\t"
        "adcs	x12, x12, x12\n\t"
        "adcs	x13, x13, x13\n\t"
        "adcs	x14, x14, x14\n\t"
        "adc	x15, xzr, xzr\n\t"
        /*  A[0] * A[0] */
        "umulh	x26, x4, x4\n\t"
        "mul	x8, x4, x4\n\t"
        /*  A[1] * A[1] */
        "mul	x25, x5, x5\n\t"
        "adds	x9, x9, x26\n\t"
        "umulh	x26, x5, x5\n\t"
        "adcs	x10, x10, x25\n\t"
        /*  A[2] * A[2] */
        "mul	x25, x6, x6\n\t"
        "adcs	x11, x11, x26\n\t"
        "umulh	x26, x6, x6\n\t"
        "adcs	x12, x12, x25\n\t"
        /*  A[3] * A[3] */
        "mul	x25, x7, x7\n\t"
        "adcs	x13, x13, x26\n\t"
        "umulh	x26, x7, x7\n\t"
        "adcs	x14, x14, x25\n\t"
        "adc	x15, x15, x26\n\t"
        /* Reduce */
        "mov	x25, #38\n\t"
        "mul	x26, x25, x15\n\t"
        "adds	x11, x11, x26\n\t"
        "umulh	x27, x25, x15\n\t"
        "adc	x27, x27, xzr\n\t"
        "mov	x25, #19\n\t"
        "extr	x27, x27, x11, #63\n\t"
        "mul	x27, x27, x25\n\t"
        "and	x11, x11, #0x7fffffffffffffff\n\t"
        "mov	x25, #38\n\t"
        "mul	x26, x25, x12\n\t"
        "adds	x8, x8, x26\n\t"
        "umulh	x12, x25, x12\n\t"
        "mul	x26, x25, x13\n\t"
        "adcs	x9, x9, x26\n\t"
        "umulh	x13, x25, x13\n\t"
        "mul	x26, x25, x14\n\t"
        "adcs	x10, x10, x26\n\t"
        "umulh	x14, x25, x14\n\t"
        "adc	x11, x11, xzr\n\t"
        /*  Add high product results in */
        "adds	x8, x8, x27\n\t"
        "adcs	x9, x9, x12\n\t"
        "adcs	x10, x10, x13\n\t"
        "adc	x11, x11, x14\n\t"
        /* Store */
        "stp	x8, x9, [x0]\n\t"
        "stp	x10, x11, [x0, #16]\n\t"
        "add	x2, x1, #32\n\t"
        "sub	x0, x0, #32\n\t"
        /* Square */
        "ldp	x16, x17, [x2]\n\t"
        "ldp	x19, x20, [x2, #16]\n\t"
        /*  A[0] * A[1] */
        "umulh	x23, x16, x17\n\t"
        "mul	x22, x16, x17\n\t"
        /*  A[0] * A[3] */
        "umulh	x4, x16, x20\n\t"
        "mul	x24, x16, x20\n\t"
        /*  A[0] * A[2] */
        "mul	x25, x16, x19\n\t"
        "adds	x23, x23, x25\n\t"
        "umulh	x26, x16, x19\n\t"
        "adcs	x24, x24, x26\n\t"
        /*  A[1] * A[3] */
        "mul	x25, x17, x20\n\t"
        "adcs	x4, x4, x25\n\t"
        "umulh	x5, x17, x20\n\t"
        "adc	x5, x5, xzr\n\t"
        /*  A[1] * A[2] */
        "mul	x25, x17, x19\n\t"
        "adds	x24, x24, x25\n\t"
        "umulh	x26, x17, x19\n\t"
        "adcs	x4, x4, x26\n\t"
        /*  A[2] * A[3] */
        "mul	x25, x19, x20\n\t"
        "adcs	x5, x5, x25\n\t"
        "umulh	x6, x19, x20\n\t"
        "adc	x6, x6, xzr\n\t"
        /* Double */
        "adds	x22, x22, x22\n\t"
        "adcs	x23, x23, x23\n\t"
        "adcs	x24, x24, x24\n\t"
        "adcs	x4, x4, x4\n\t"
        "adcs	x5, x5, x5\n\t"
        "adcs	x6, x6, x6\n\t"
        "adc	x7, xzr, xzr\n\t"
        /*  A[0] * A[0] */
        "umulh	x26, x16, x16\n\t"
        "mul	x21, x16, x16\n\t"
        /*  A[1] * A[1] */
        "mul	x25, x17, x17\n\t"
        "adds	x22, x22, x26\n\t"
        "umulh	x26, x17, x17\n\t"
        "adcs	x23, x23, x25\n\t"
        /*  A[2] * A[2] */
        "mul	x25, x19, x19\n\t"
        "adcs	x24, x24, x26\n\t"
        "umulh	x26, x19, x19\n\t"
        "adcs	x4, x4, x25\n\t"
        /*  A[3] * A[3] */
        "mul	x25, x20, x20\n\t"
        "adcs	x5, x5, x26\n\t"
        "umulh	x26, x20, x20\n\t"
        "adcs	x6, x6, x25\n\t"
        "adc	x7, x7, x26\n\t"
        /* Reduce */
        "mov	x25, #38\n\t"
        "mul	x26, x25, x7\n\t"
        "adds	x24, x24, x26\n\t"
        "umulh	x27, x25, x7\n\t"
        "adc	x27, x27, xzr\n\t"
        "mov	x25, #19\n\t"
        "extr	x27, x27, x24, #63\n\t"
        "mul	x27, x27, x25\n\t"
        "and	x24, x24, #0x7fffffffffffffff\n\t"
        "mov	x25, #38\n\t"
        "mul	x26, x25, x4\n\t"
        "adds	x21, x21, x26\n\t"
        "umulh	x4, x25, x4\n\t"
        "mul	x26, x25, x5\n\t"
        "adcs	x22, x22, x26\n\t"
        "umulh	x5, x25, x5\n\t"
        "mul	x26, x25, x6\n\t"
        "adcs	x23, x23, x26\n\t"
        "umulh	x6, x25, x6\n\t"
        "adc	x24, x24, xzr\n\t"
        /*  Add high product results in */
        "adds	x21, x21, x27\n\t"
        "adcs	x22, x22, x4\n\t"
        "adcs	x23, x23, x5\n\t"
        "adc	x24, x24, x6\n\t"
        "add	x3, x0, #32\n\t"
        "mov	x2, x0\n\t"
        "add	x1, x0, #32\n\t"
        /* Add */
        "adds	x4, x21, x8\n\t"
        "adcs	x5, x22, x9\n\t"
        "adcs	x6, x23, x10\n\t"
        "adcs	x7, x24, x11\n\t"
        "cset	x28, cs\n\t"
        "mov	x25, #19\n\t"
        "extr	x28, x28, x7, #63\n\t"
        "mul	x25, x28, x25\n\t"
        /*   Sub modulus (if overflow) */
        "adds	x4, x4, x25\n\t"
        "adcs	x5, x5, xzr\n\t"
        "and	x7, x7, #0x7fffffffffffffff\n\t"
        "adcs	x6, x6, xzr\n\t"
        "adc	x7, x7, xzr\n\t"
        /* Sub */
        "subs	x12, x21, x8\n\t"
        "sbcs	x13, x22, x9\n\t"
        "sbcs	x14, x23, x10\n\t"
        "sbcs	x15, x24, x11\n\t"
        "csetm	x28, cc\n\t"
        "mov	x25, #-19\n\t"
        "extr	x28, x28, x15, #63\n\t"
        "mul	x25, x28, x25\n\t"
        /*   Add modulus (if underflow) */
        "subs	x12, x12, x25\n\t"
        "sbcs	x13, x13, xzr\n\t"
        "and	x15, x15, #0x7fffffffffffffff\n\t"
        "sbcs	x14, x14, xzr\n\t"
        "sbc	x15, x15, xzr\n\t"
        "stp	x4, x5, [x0]\n\t"
        "stp	x6, x7, [x0, #16]\n\t"
        "stp	x12, x13, [x1]\n\t"
        "stp	x14, x15, [x1, #16]\n\t"
        "ldr	x1, [x29, #24]\n\t"
        "add	x2, x1, #32\n\t"
        "sub	x0, x0, #32\n\t"
        /* Add */
        "ldp	x8, x9, [x1]\n\t"
        "ldp	x10, x11, [x1, #16]\n\t"
        "adds	x8, x8, x16\n\t"
        "adcs	x9, x9, x17\n\t"
        "adcs	x10, x10, x19\n\t"
        "adcs	x11, x11, x20\n\t"
        "cset	x28, cs\n\t"
        "mov	x25, #19\n\t"
        /*   Mask the modulus */
        "extr	x28, x28, x11, #63\n\t"
        "mul	x25, x28, x25\n\t"
        /*   Sub modulus (if overflow) */
        "adds	x8, x8, x25\n\t"
        "adcs	x9, x9, xzr\n\t"
        "and	x11, x11, #0x7fffffffffffffff\n\t"
        "adcs	x10, x10, xzr\n\t"
        "adc	x11, x11, xzr\n\t"
        "mov	x1, x0\n\t"
        /* Square */
        /*  A[0] * A[1] */
        "umulh	x23, x8, x9\n\t"
        "mul	x22, x8, x9\n\t"
        /*  A[0] * A[3] */
        "umulh	x4, x8, x11\n\t"
        "mul	x24, x8, x11\n\t"
        /*  A[0] * A[2] */
        "mul	x25, x8, x10\n\t"
        "adds	x23, x23, x25\n\t"
        "umulh	x26, x8, x10\n\t"
        "adcs	x24, x24, x26\n\t"
        /*  A[1] * A[3] */
        "mul	x25, x9, x11\n\t"
        "adcs	x4, x4, x25\n\t"
        "umulh	x5, x9, x11\n\t"
        "adc	x5, x5, xzr\n\t"
        /*  A[1] * A[2] */
        "mul	x25, x9, x10\n\t"
        "adds	x24, x24, x25\n\t"
        "umulh	x26, x9, x10\n\t"
        "adcs	x4, x4, x26\n\t"
        /*  A[2] * A[3] */
        "mul	x25, x10, x11\n\t"
        "adcs	x5, x5, x25\n\t"
        "umulh	x6, x10, x11\n\t"
        "adc	x6, x6, xzr\n\t"
        /* Double */
        "adds	x22, x22, x22\n\t"
        "adcs	x23, x23, x23\n\t"
        "adcs	x24, x24, x24\n\t"
        "adcs	x4, x4, x4\n\t"
        "adcs	x5, x5, x5\n\t"
        "adcs	x6, x6, x6\n\t"
        "adc	x7, xzr, xzr\n\t"
        /*  A[0] * A[0] */
        "umulh	x26, x8, x8\n\t"
        "mul	x21, x8, x8\n\t"
        /*  A[1] * A[1] */
        "mul	x25, x9, x9\n\t"
        "adds	x22, x22, x26\n\t"
        "umulh	x26, x9, x9\n\t"
        "adcs	x23, x23, x25\n\t"
        /*  A[2] * A[2] */
        "mul	x25, x10, x10\n\t"
        "adcs	x24, x24, x26\n\t"
        "umulh	x26, x10, x10\n\t"
        "adcs	x4, x4, x25\n\t"
        /*  A[3] * A[3] */
        "mul	x25, x11, x11\n\t"
        "adcs	x5, x5, x26\n\t"
        "umulh	x26, x11, x11\n\t"
        "adcs	x6, x6, x25\n\t"
        "adc	x7, x7, x26\n\t"
        /* Reduce */
        "mov	x25, #38\n\t"
        "mul	x26, x25, x7\n\t"
        "adds	x24, x24, x26\n\t"
        "umulh	x27, x25, x7\n\t"
        "adc	x27, x27, xzr\n\t"
        "mov	x25, #19\n\t"
        "extr	x27, x27, x24, #63\n\t"
        "mul	x27, x27, x25\n\t"
        "and	x24, x24, #0x7fffffffffffffff\n\t"
        "mov	x25, #38\n\t"
        "mul	x26, x25, x4\n\t"
        "adds	x21, x21, x26\n\t"
        "umulh	x4, x25, x4\n\t"
        "mul	x26, x25, x5\n\t"
        "adcs	x22, x22, x26\n\t"
        "umulh	x5, x25, x5\n\t"
        "mul	x26, x25, x6\n\t"
        "adcs	x23, x23, x26\n\t"
        "umulh	x6, x25, x6\n\t"
        "adc	x24, x24, xzr\n\t"
        /*  Add high product results in */
        "adds	x21, x21, x27\n\t"
        "adcs	x22, x22, x4\n\t"
        "adcs	x23, x23, x5\n\t"
        "adc	x24, x24, x6\n\t"
        "add	x2, x0, #32\n\t"
        /* Sub */
        "ldp	x8, x9, [x2]\n\t"
        "ldp	x10, x11, [x2, #16]\n\t"
        "subs	x21, x21, x8\n\t"
        "sbcs	x22, x22, x9\n\t"
        "sbcs	x23, x23, x10\n\t"
        "sbcs	x24, x24, x11\n\t"
        "csetm	x28, cc\n\t"
        "mov	x25, #-19\n\t"
        /*   Mask the modulus */
        "extr	x28, x28, x24, #63\n\t"
        "mul	x25, x28, x25\n\t"
        /*   Add modulus (if underflow) */
        "subs	x21, x21, x25\n\t"
        "sbcs	x22, x22, xzr\n\t"
        "and	x24, x24, #0x7fffffffffffffff\n\t"
        "sbcs	x23, x23, xzr\n\t"
        "sbc	x24, x24, xzr\n\t"
        "stp	x21, x22, [x0]\n\t"
        "stp	x23, x24, [x0, #16]\n\t"
        "ldr	x2, [x29, #24]\n\t"
        "add	x2, x2, #0x40\n\t"
        "add	x0, x0, #0x60\n\t"
        /* Square * 2 */
        "ldp	x16, x17, [x2]\n\t"
        "ldp	x19, x20, [x2, #16]\n\t"
        /*  A[0] * A[1] */
        "umulh	x6, x16, x17\n\t"
        "mul	x5, x16, x17\n\t"
        /*  A[0] * A[3] */
        "umulh	x8, x16, x20\n\t"
        "mul	x7, x16, x20\n\t"
        /*  A[0] * A[2] */
        "mul	x25, x16, x19\n\t"
        "adds	x6, x6, x25\n\t"
        "umulh	x26, x16, x19\n\t"
        "adcs	x7, x7, x26\n\t"
        /*  A[1] * A[3] */
        "mul	x25, x17, x20\n\t"
        "adcs	x8, x8, x25\n\t"
        "umulh	x9, x17, x20\n\t"
        "adc	x9, x9, xzr\n\t"
        /*  A[1] * A[2] */
        "mul	x25, x17, x19\n\t"
        "adds	x7, x7, x25\n\t"
        "umulh	x26, x17, x19\n\t"
        "adcs	x8, x8, x26\n\t"
        /*  A[2] * A[3] */
        "mul	x25, x19, x20\n\t"
        "adcs	x9, x9, x25\n\t"
        "umulh	x10, x19, x20\n\t"
        "adc	x10, x10, xzr\n\t"
        /* Double */
        "adds	x5, x5, x5\n\t"
        "adcs	x6, x6, x6\n\t"
        "adcs	x7, x7, x7\n\t"
        "adcs	x8, x8, x8\n\t"
        "adcs	x9, x9, x9\n\t"
        "adcs	x10, x10, x10\n\t"
        "adc	x11, xzr, xzr\n\t"
        /*  A[0] * A[0] */
        "umulh	x26, x16, x16\n\t"
        "mul	x4, x16, x16\n\t"
        /*  A[1] * A[1] */
        "mul	x25, x17, x17\n\t"
        "adds	x5, x5, x26\n\t"
        "umulh	x26, x17, x17\n\t"
        "adcs	x6, x6, x25\n\t"
        /*  A[2] * A[2] */
        "mul	x25, x19, x19\n\t"
        "adcs	x7, x7, x26\n\t"
        "umulh	x26, x19, x19\n\t"
        "adcs	x8, x8, x25\n\t"
        /*  A[3] * A[3] */
        "mul	x25, x20, x20\n\t"
        "adcs	x9, x9, x26\n\t"
        "umulh	x26, x20, x20\n\t"
        "adcs	x10, x10, x25\n\t"
        "adc	x11, x11, x26\n\t"
        /* Reduce */
        "mov	x25, #38\n\t"
        "mul	x26, x25, x11\n\t"
        "adds	x7, x7, x26\n\t"
        "umulh	x27, x25, x11\n\t"
        "adc	x27, x27, xzr\n\t"
        "mov	x25, #19\n\t"
        "extr	x27, x27, x7, #63\n\t"
        "mul	x27, x27, x25\n\t"
        "and	x7, x7, #0x7fffffffffffffff\n\t"
        "mov	x25, #38\n\t"
        "mul	x26, x25, x8\n\t"
        "adds	x4, x4, x26\n\t"
        "umulh	x8, x25, x8\n\t"
        "mul	x26, x25, x9\n\t"
        "adcs	x5, x5, x26\n\t"
        "umulh	x9, x25, x9\n\t"
        "mul	x26, x25, x10\n\t"
        "adcs	x6, x6, x26\n\t"
        "umulh	x10, x25, x10\n\t"
        "adc	x7, x7, xzr\n\t"
        /*  Add high product results in */
        "adds	x4, x4, x27\n\t"
        "adcs	x5, x5, x8\n\t"
        "adcs	x6, x6, x9\n\t"
        "adc	x7, x7, x10\n\t"
        "mov	x25, #19\n\t"
        "lsr	x26, x7, #62\n\t"
        "extr	x7, x7, x6, #63\n\t"
        "extr	x6, x6, x5, #63\n\t"
        "extr	x5, x5, x4, #63\n\t"
        "lsl	x4, x4, #1\n\t"
        "mul	x26, x26, x25\n\t"
        "adds	x4, x4, x26\n\t"
        "adcs	x5, x5, xzr\n\t"
        "and	x7, x7, #0x7fffffffffffffff\n\t"
        "adcs	x6, x6, xzr\n\t"
        "adc	x7, x7, xzr\n\t"
        /* Store */
        "sub	x1, x0, #32\n\t"
        /* Sub */
        "subs	x4, x4, x12\n\t"
        "sbcs	x5, x5, x13\n\t"
        "sbcs	x6, x6, x14\n\t"
        "sbcs	x7, x7, x15\n\t"
        "csetm	x28, cc\n\t"
        "mov	x25, #-19\n\t"
        /*   Mask the modulus */
        "extr	x28, x28, x7, #63\n\t"
        "mul	x25, x28, x25\n\t"
        /*   Add modulus (if underflow) */
        "subs	x4, x4, x25\n\t"
        "sbcs	x5, x5, xzr\n\t"
        "and	x7, x7, #0x7fffffffffffffff\n\t"
        "sbcs	x6, x6, xzr\n\t"
        "sbc	x7, x7, xzr\n\t"
        "stp	x4, x5, [x0]\n\t"
        "stp	x6, x7, [x0, #16]\n\t"
        "ldp	x29, x30, [sp], #32\n\t"
        : [r] "+r" (r)
        : [p] "r" (p)
        : "memory", "cc", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10",
            "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20",
            "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28"
    );
}

void ge_madd(ge_p1p1* r, const ge_p3* p, const ge_precomp* q)
{
    __asm__ __volatile__ (
        "stp	x29, x30, [sp, #-48]!\n\t"
        "add	x29, sp, #0\n\t"
        "str	%x[r], [x29, #16]\n\t"
        "str	%x[p], [x29, #24]\n\t"
        "str	%x[q], [x29, #32]\n\t"
        "mov	x3, x1\n\t"
        "add	x2, x1, #32\n\t"
        "add	x1, x0, #32\n\t"
        /* Add */
        "ldp	x8, x9, [x2]\n\t"
        "ldp	x10, x11, [x2, #16]\n\t"
        "ldp	x4, x5, [x3]\n\t"
        "ldp	x6, x7, [x3, #16]\n\t"
        "adds	x16, x8, x4\n\t"
        "adcs	x17, x9, x5\n\t"
        "adcs	x19, x10, x6\n\t"
        "adcs	x20, x11, x7\n\t"
        "cset	x28, cs\n\t"
        "mov	x25, #19\n\t"
        "extr	x28, x28, x20, #63\n\t"
        "mul	x25, x28, x25\n\t"
        /*   Sub modulus (if overflow) */
        "adds	x16, x16, x25\n\t"
        "adcs	x17, x17, xzr\n\t"
        "and	x20, x20, #0x7fffffffffffffff\n\t"
        "adcs	x19, x19, xzr\n\t"
        "adc	x20, x20, xzr\n\t"
        /* Sub */
        "subs	x12, x8, x4\n\t"
        "sbcs	x13, x9, x5\n\t"
        "sbcs	x14, x10, x6\n\t"
        "sbcs	x15, x11, x7\n\t"
        "csetm	x28, cc\n\t"
        "mov	x25, #-19\n\t"
        "extr	x28, x28, x15, #63\n\t"
        "mul	x25, x28, x25\n\t"
        /*   Add modulus (if underflow) */
        "subs	x12, x12, x25\n\t"
        "sbcs	x13, x13, xzr\n\t"
        "and	x15, x15, #0x7fffffffffffffff\n\t"
        "sbcs	x14, x14, xzr\n\t"
        "sbc	x15, x15, xzr\n\t"
        "ldr	x2, [x29, #32]\n\t"
        "mov	x1, x0\n\t"
        /* Multiply */
        "ldp	x8, x9, [x2]\n\t"
        "ldp	x10, x11, [x2, #16]\n\t"
        /* A[0] * B[0] */
        "umulh	x22, x16, x8\n\t"
        "mul	x21, x16, x8\n\t"
        /* A[2] * B[0] */
        "umulh	x24, x19, x8\n\t"
        "mul	x23, x19, x8\n\t"
        /* A[1] * B[0] */
        "mul	x25, x17, x8\n\t"
        "adds	x22, x22, x25\n\t"
        "umulh	x26, x17, x8\n\t"
        "adcs	x23, x23, x26\n\t"
        /* A[1] * B[3] */
        "umulh	x5, x17, x11\n\t"
        "adc	x24, x24, xzr\n\t"
        "mul	x4, x17, x11\n\t"
        /* A[0] * B[1] */
        "mul	x25, x16, x9\n\t"
        "adds	x22, x22, x25\n\t"
        "umulh	x26, x16, x9\n\t"
        "adcs	x23, x23, x26\n\t"
        /* A[2] * B[1] */
        "mul	x25, x19, x9\n\t"
        "adcs	x24, x24, x25\n\t"
        "umulh	x26, x19, x9\n\t"
        "adcs	x4, x4, x26\n\t"
        "adc	x5, x5, xzr\n\t"
        /* A[1] * B[2] */
        "mul	x25, x17, x10\n\t"
        "adds	x24, x24, x25\n\t"
        "umulh	x26, x17, x10\n\t"
        "adcs	x4, x4, x26\n\t"
        "adcs	x5, x5, xzr\n\t"
        "adc	x6, xzr, xzr\n\t"
        /* A[0] * B[2] */
        "mul	x25, x16, x10\n\t"
        "adds	x23, x23, x25\n\t"
        "umulh	x26, x16, x10\n\t"
        "adcs	x24, x24, x26\n\t"
        "adcs	x4, x4, xzr\n\t"
        "adcs	x5, x5, xzr\n\t"
        "adc	x6, x6, xzr\n\t"
        /* A[1] * B[1] */
        "mul	x25, x17, x9\n\t"
        "adds	x23, x23, x25\n\t"
        "umulh	x26, x17, x9\n\t"
        "adcs	x24, x24, x26\n\t"
        /* A[3] * B[1] */
        "mul	x25, x20, x9\n\t"
        "adcs	x4, x4, x25\n\t"
        "umulh	x26, x20, x9\n\t"
        "adcs	x5, x5, x26\n\t"
        "adc	x6, x6, xzr\n\t"
        /* A[2] * B[2] */
        "mul	x25, x19, x10\n\t"
        "adds	x4, x4, x25\n\t"
        "umulh	x26, x19, x10\n\t"
        "adcs	x5, x5, x26\n\t"
        /* A[3] * B[3] */
        "mul	x25, x20, x11\n\t"
        "adcs	x6, x6, x25\n\t"
        "umulh	x7, x20, x11\n\t"
        "adc	x7, x7, xzr\n\t"
        /* A[0] * B[3] */
        "mul	x25, x16, x11\n\t"
        "adds	x24, x24, x25\n\t"
        "umulh	x26, x16, x11\n\t"
        "adcs	x4, x4, x26\n\t"
        /* A[2] * B[3] */
        "mul	x25, x19, x11\n\t"
        "adcs	x5, x5, x25\n\t"
        "umulh	x26, x19, x11\n\t"
        "adcs	x6, x6, x26\n\t"
        "adc	x7, x7, xzr\n\t"
        /* A[3] * B[0] */
        "mul	x25, x20, x8\n\t"
        "adds	x24, x24, x25\n\t"
        "umulh	x26, x20, x8\n\t"
        "adcs	x4, x4, x26\n\t"
        /* A[3] * B[2] */
        "mul	x25, x20, x10\n\t"
        "adcs	x5, x5, x25\n\t"
        "umulh	x26, x20, x10\n\t"
        "adcs	x6, x6, x26\n\t"
        "adc	x7, x7, xzr\n\t"
        /* Reduce */
        "mov	x25, #38\n\t"
        "mul	x26, x25, x7\n\t"
        "adds	x24, x24, x26\n\t"
        "umulh	x27, x25, x7\n\t"
        "adc	x27, x27, xzr\n\t"
        "mov	x25, #19\n\t"
        "extr	x27, x27, x24, #63\n\t"
        "mul	x27, x27, x25\n\t"
        "and	x24, x24, #0x7fffffffffffffff\n\t"
        "mov	x25, #38\n\t"
        "mul	x26, x25, x4\n\t"
        "adds	x21, x21, x26\n\t"
        "umulh	x4, x25, x4\n\t"
        "mul	x26, x25, x5\n\t"
        "adcs	x22, x22, x26\n\t"
        "umulh	x5, x25, x5\n\t"
        "mul	x26, x25, x6\n\t"
        "adcs	x23, x23, x26\n\t"
        "umulh	x6, x25, x6\n\t"
        "adc	x24, x24, xzr\n\t"
        /*  Add high product results in */
        "adds	x21, x21, x27\n\t"
        "adcs	x22, x22, x4\n\t"
        "adcs	x23, x23, x5\n\t"
        "adc	x24, x24, x6\n\t"
        "add	x2, x2, #32\n\t"
        "add	x1, x0, #32\n\t"
        "add	x0, x0, #32\n\t"
        /* Multiply */
        "ldp	x16, x17, [x2]\n\t"
        "ldp	x19, x20, [x2, #16]\n\t"
        /* A[0] * B[0] */
        "umulh	x5, x12, x16\n\t"
        "mul	x4, x12, x16\n\t"
        /* A[2] * B[0] */
        "umulh	x7, x14, x16\n\t"
        "mul	x6, x14, x16\n\t"
        /* A[1] * B[0] */
        "mul	x25, x13, x16\n\t"
        "adds	x5, x5, x25\n\t"
        "umulh	x26, x13, x16\n\t"
        "adcs	x6, x6, x26\n\t"
        /* A[1] * B[3] */
        "umulh	x9, x13, x20\n\t"
        "adc	x7, x7, xzr\n\t"
        "mul	x8, x13, x20\n\t"
        /* A[0] * B[1] */
        "mul	x25, x12, x17\n\t"
        "adds	x5, x5, x25\n\t"
        "umulh	x26, x12, x17\n\t"
        "adcs	x6, x6, x26\n\t"
        /* A[2] * B[1] */
        "mul	x25, x14, x17\n\t"
        "adcs	x7, x7, x25\n\t"
        "umulh	x26, x14, x17\n\t"
        "adcs	x8, x8, x26\n\t"
        "adc	x9, x9, xzr\n\t"
        /* A[1] * B[2] */
        "mul	x25, x13, x19\n\t"
        "adds	x7, x7, x25\n\t"
        "umulh	x26, x13, x19\n\t"
        "adcs	x8, x8, x26\n\t"
        "adcs	x9, x9, xzr\n\t"
        "adc	x10, xzr, xzr\n\t"
        /* A[0] * B[2] */
        "mul	x25, x12, x19\n\t"
        "adds	x6, x6, x25\n\t"
        "umulh	x26, x12, x19\n\t"
        "adcs	x7, x7, x26\n\t"
        "adcs	x8, x8, xzr\n\t"
        "adcs	x9, x9, xzr\n\t"
        "adc	x10, x10, xzr\n\t"
        /* A[1] * B[1] */
        "mul	x25, x13, x17\n\t"
        "adds	x6, x6, x25\n\t"
        "umulh	x26, x13, x17\n\t"
        "adcs	x7, x7, x26\n\t"
        /* A[3] * B[1] */
        "mul	x25, x15, x17\n\t"
        "adcs	x8, x8, x25\n\t"
        "umulh	x26, x15, x17\n\t"
        "adcs	x9, x9, x26\n\t"
        "adc	x10, x10, xzr\n\t"
        /* A[2] * B[2] */
        "mul	x25, x14, x19\n\t"
        "adds	x8, x8, x25\n\t"
        "umulh	x26, x14, x19\n\t"
        "adcs	x9, x9, x26\n\t"
        /* A[3] * B[3] */
        "mul	x25, x15, x20\n\t"
        "adcs	x10, x10, x25\n\t"
        "umulh	x11, x15, x20\n\t"
        "adc	x11, x11, xzr\n\t"
        /* A[0] * B[3] */
        "mul	x25, x12, x20\n\t"
        "adds	x7, x7, x25\n\t"
        "umulh	x26, x12, x20\n\t"
        "adcs	x8, x8, x26\n\t"
        /* A[2] * B[3] */
        "mul	x25, x14, x20\n\t"
        "adcs	x9, x9, x25\n\t"
        "umulh	x26, x14, x20\n\t"
        "adcs	x10, x10, x26\n\t"
        "adc	x11, x11, xzr\n\t"
        /* A[3] * B[0] */
        "mul	x25, x15, x16\n\t"
        "adds	x7, x7, x25\n\t"
        "umulh	x26, x15, x16\n\t"
        "adcs	x8, x8, x26\n\t"
        /* A[3] * B[2] */
        "mul	x25, x15, x19\n\t"
        "adcs	x9, x9, x25\n\t"
        "umulh	x26, x15, x19\n\t"
        "adcs	x10, x10, x26\n\t"
        "adc	x11, x11, xzr\n\t"
        /* Reduce */
        "mov	x25, #38\n\t"
        "mul	x26, x25, x11\n\t"
        "adds	x7, x7, x26\n\t"
        "umulh	x27, x25, x11\n\t"
        "adc	x27, x27, xzr\n\t"
        "mov	x25, #19\n\t"
        "extr	x27, x27, x7, #63\n\t"
        "mul	x27, x27, x25\n\t"
        "and	x7, x7, #0x7fffffffffffffff\n\t"
        "mov	x25, #38\n\t"
        "mul	x26, x25, x8\n\t"
        "adds	x4, x4, x26\n\t"
        "umulh	x8, x25, x8\n\t"
        "mul	x26, x25, x9\n\t"
        "adcs	x5, x5, x26\n\t"
        "umulh	x9, x25, x9\n\t"
        "mul	x26, x25, x10\n\t"
        "adcs	x6, x6, x26\n\t"
        "umulh	x10, x25, x10\n\t"
        "adc	x7, x7, xzr\n\t"
        /*  Add high product results in */
        "adds	x4, x4, x27\n\t"
        "adcs	x5, x5, x8\n\t"
        "adcs	x6, x6, x9\n\t"
        "adc	x7, x7, x10\n\t"
        "mov	x3, x0\n\t"
        "sub	x2, x0, #32\n\t"
        "sub	x1, x0, #32\n\t"
        /* Add */
        "adds	x8, x21, x4\n\t"
        "adcs	x9, x22, x5\n\t"
        "adcs	x10, x23, x6\n\t"
        "adcs	x11, x24, x7\n\t"
        "cset	x28, cs\n\t"
        "mov	x25, #19\n\t"
        "extr	x28, x28, x11, #63\n\t"
        "mul	x25, x28, x25\n\t"
        /*   Sub modulus (if overflow) */
        "adds	x8, x8, x25\n\t"
        "adcs	x9, x9, xzr\n\t"
        "and	x11, x11, #0x7fffffffffffffff\n\t"
        "adcs	x10, x10, xzr\n\t"
        "adc	x11, x11, xzr\n\t"
        /* Sub */
        "subs	x12, x21, x4\n\t"
        "sbcs	x13, x22, x5\n\t"
        "sbcs	x14, x23, x6\n\t"
        "sbcs	x15, x24, x7\n\t"
        "csetm	x28, cc\n\t"
        "mov	x25, #-19\n\t"
        "extr	x28, x28, x15, #63\n\t"
        "mul	x25, x28, x25\n\t"
        /*   Add modulus (if underflow) */
        "subs	x12, x12, x25\n\t"
        "sbcs	x13, x13, xzr\n\t"
        "and	x15, x15, #0x7fffffffffffffff\n\t"
        "sbcs	x14, x14, xzr\n\t"
        "sbc	x15, x15, xzr\n\t"
        "stp	x8, x9, [x0]\n\t"
        "stp	x10, x11, [x0, #16]\n\t"
        "stp	x12, x13, [x1]\n\t"
        "stp	x14, x15, [x1, #16]\n\t"
        "ldr	x1, [x29, #24]\n\t"
        "ldr	x2, [x29, #32]\n\t"
        "add	x2, x2, #0x40\n\t"
        "add	x1, x1, #0x60\n\t"
        "add	x0, x0, #0x40\n\t"
        /* Multiply */
        "ldp	x21, x22, [x1]\n\t"
        "ldp	x23, x24, [x1, #16]\n\t"
        "ldp	x4, x5, [x2]\n\t"
        "ldp	x6, x7, [x2, #16]\n\t"
        /* A[0] * B[0] */
        "umulh	x17, x21, x4\n\t"
        "mul	x16, x21, x4\n\t"
        /* A[2] * B[0] */
        "umulh	x20, x23, x4\n\t"
        "mul	x19, x23, x4\n\t"
        /* A[1] * B[0] */
        "mul	x25, x22, x4\n\t"
        "adds	x17, x17, x25\n\t"
        "umulh	x26, x22, x4\n\t"
        "adcs	x19, x19, x26\n\t"
        /* A[1] * B[3] */
        "umulh	x9, x22, x7\n\t"
        "adc	x20, x20, xzr\n\t"
        "mul	x8, x22, x7\n\t"
        /* A[0] * B[1] */
        "mul	x25, x21, x5\n\t"
        "adds	x17, x17, x25\n\t"
        "umulh	x26, x21, x5\n\t"
        "adcs	x19, x19, x26\n\t"
        /* A[2] * B[1] */
        "mul	x25, x23, x5\n\t"
        "adcs	x20, x20, x25\n\t"
        "umulh	x26, x23, x5\n\t"
        "adcs	x8, x8, x26\n\t"
        "adc	x9, x9, xzr\n\t"
        /* A[1] * B[2] */
        "mul	x25, x22, x6\n\t"
        "adds	x20, x20, x25\n\t"
        "umulh	x26, x22, x6\n\t"
        "adcs	x8, x8, x26\n\t"
        "adcs	x9, x9, xzr\n\t"
        "adc	x10, xzr, xzr\n\t"
        /* A[0] * B[2] */
        "mul	x25, x21, x6\n\t"
        "adds	x19, x19, x25\n\t"
        "umulh	x26, x21, x6\n\t"
        "adcs	x20, x20, x26\n\t"
        "adcs	x8, x8, xzr\n\t"
        "adcs	x9, x9, xzr\n\t"
        "adc	x10, x10, xzr\n\t"
        /* A[1] * B[1] */
        "mul	x25, x22, x5\n\t"
        "adds	x19, x19, x25\n\t"
        "umulh	x26, x22, x5\n\t"
        "adcs	x20, x20, x26\n\t"
        /* A[3] * B[1] */
        "mul	x25, x24, x5\n\t"
        "adcs	x8, x8, x25\n\t"
        "umulh	x26, x24, x5\n\t"
        "adcs	x9, x9, x26\n\t"
        "adc	x10, x10, xzr\n\t"
        /* A[2] * B[2] */
        "mul	x25, x23, x6\n\t"
        "adds	x8, x8, x25\n\t"
        "umulh	x26, x23, x6\n\t"
        "adcs	x9, x9, x26\n\t"
        /* A[3] * B[3] */
        "mul	x25, x24, x7\n\t"
        "adcs	x10, x10, x25\n\t"
        "umulh	x11, x24, x7\n\t"
        "adc	x11, x11, xzr\n\t"
        /* A[0] * B[3] */
        "mul	x25, x21, x7\n\t"
        "adds	x20, x20, x25\n\t"
        "umulh	x26, x21, x7\n\t"
        "adcs	x8, x8, x26\n\t"
        /* A[2] * B[3] */
        "mul	x25, x23, x7\n\t"
        "adcs	x9, x9, x25\n\t"
        "umulh	x26, x23, x7\n\t"
        "adcs	x10, x10, x26\n\t"
        "adc	x11, x11, xzr\n\t"
        /* A[3] * B[0] */
        "mul	x25, x24, x4\n\t"
        "adds	x20, x20, x25\n\t"
        "umulh	x26, x24, x4\n\t"
        "adcs	x8, x8, x26\n\t"
        /* A[3] * B[2] */
        "mul	x25, x24, x6\n\t"
        "adcs	x9, x9, x25\n\t"
        "umulh	x26, x24, x6\n\t"
        "adcs	x10, x10, x26\n\t"
        "adc	x11, x11, xzr\n\t"
        /* Reduce */
        "mov	x25, #38\n\t"
        "mul	x26, x25, x11\n\t"
        "adds	x20, x20, x26\n\t"
        "umulh	x27, x25, x11\n\t"
        "adc	x27, x27, xzr\n\t"
        "mov	x25, #19\n\t"
        "extr	x27, x27, x20, #63\n\t"
        "mul	x27, x27, x25\n\t"
        "and	x20, x20, #0x7fffffffffffffff\n\t"
        "mov	x25, #38\n\t"
        "mul	x26, x25, x8\n\t"
        "adds	x16, x16, x26\n\t"
        "umulh	x8, x25, x8\n\t"
        "mul	x26, x25, x9\n\t"
        "adcs	x17, x17, x26\n\t"
        "umulh	x9, x25, x9\n\t"
        "mul	x26, x25, x10\n\t"
        "adcs	x19, x19, x26\n\t"
        "umulh	x10, x25, x10\n\t"
        "adc	x20, x20, xzr\n\t"
        /*  Add high product results in */
        "adds	x16, x16, x27\n\t"
        "adcs	x17, x17, x8\n\t"
        "adcs	x19, x19, x9\n\t"
        "adc	x20, x20, x10\n\t"
        "sub	x1, x1, #32\n\t"
        /* Double */
        "ldp	x12, x13, [x1]\n\t"
        "ldp	x14, x15, [x1, #16]\n\t"
        "adds	x12, x12, x12\n\t"
        "adcs	x13, x13, x13\n\t"
        "adcs	x14, x14, x14\n\t"
        "adc	x15, x15, x15\n\t"
        "mov	x25, #-19\n\t"
        "asr	x28, x15, #63\n\t"
        /*   Mask the modulus */
        "and	x25, x28, x25\n\t"
        "and	x26, x28, #0x7fffffffffffffff\n\t"
        /*   Sub modulus (if overflow) */
        "subs	x12, x12, x25\n\t"
        "sbcs	x13, x13, x28\n\t"
        "sbcs	x14, x14, x28\n\t"
        "sbc	x15, x15, x26\n\t"
        "mov	x3, x0\n\t"
        "sub	x2, x0, #32\n\t"
        "mov	x1, x0\n\t"
        "sub	x0, x0, #32\n\t"
        /* Add */
        "adds	x8, x12, x16\n\t"
        "adcs	x9, x13, x17\n\t"
        "adcs	x10, x14, x19\n\t"
        "adcs	x11, x15, x20\n\t"
        "cset	x28, cs\n\t"
        "mov	x25, #19\n\t"
        "extr	x28, x28, x11, #63\n\t"
        "mul	x25, x28, x25\n\t"
        /*   Sub modulus (if overflow) */
        "adds	x8, x8, x25\n\t"
        "adcs	x9, x9, xzr\n\t"
        "and	x11, x11, #0x7fffffffffffffff\n\t"
        "adcs	x10, x10, xzr\n\t"
        "adc	x11, x11, xzr\n\t"
        /* Sub */
        "subs	x4, x12, x16\n\t"
        "sbcs	x5, x13, x17\n\t"
        "sbcs	x6, x14, x19\n\t"
        "sbcs	x7, x15, x20\n\t"
        "csetm	x28, cc\n\t"
        "mov	x25, #-19\n\t"
        "extr	x28, x28, x7, #63\n\t"
        "mul	x25, x28, x25\n\t"
        /*   Add modulus (if underflow) */
        "subs	x4, x4, x25\n\t"
        "sbcs	x5, x5, xzr\n\t"
        "and	x7, x7, #0x7fffffffffffffff\n\t"
        "sbcs	x6, x6, xzr\n\t"
        "sbc	x7, x7, xzr\n\t"
        "stp	x8, x9, [x0]\n\t"
        "stp	x10, x11, [x0, #16]\n\t"
        "stp	x4, x5, [x1]\n\t"
        "stp	x6, x7, [x1, #16]\n\t"
        "ldp	x29, x30, [sp], #48\n\t"
        : [r] "+r" (r)
        : [p] "r" (p), [q] "r" (q)
        : "memory", "cc", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10",
            "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20",
            "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28"
    );
}

void ge_msub(ge_p1p1* r, const ge_p3* p, const ge_precomp* q)
{
    __asm__ __volatile__ (
        "stp	x29, x30, [sp, #-48]!\n\t"
        "add	x29, sp, #0\n\t"
        "str	%x[r], [x29, #16]\n\t"
        "str	%x[p], [x29, #24]\n\t"
        "str	%x[q], [x29, #32]\n\t"
        "mov	x3, x1\n\t"
        "add	x2, x1, #32\n\t"
        "add	x1, x0, #32\n\t"
        /* Add */
        "ldp	x8, x9, [x2]\n\t"
        "ldp	x10, x11, [x2, #16]\n\t"
        "ldp	x4, x5, [x3]\n\t"
        "ldp	x6, x7, [x3, #16]\n\t"
        "adds	x16, x8, x4\n\t"
        "adcs	x17, x9, x5\n\t"
        "adcs	x19, x10, x6\n\t"
        "adcs	x20, x11, x7\n\t"
        "cset	x28, cs\n\t"
        "mov	x25, #19\n\t"
        "extr	x28, x28, x20, #63\n\t"
        "mul	x25, x28, x25\n\t"
        /*   Sub modulus (if overflow) */
        "adds	x16, x16, x25\n\t"
        "adcs	x17, x17, xzr\n\t"
        "and	x20, x20, #0x7fffffffffffffff\n\t"
        "adcs	x19, x19, xzr\n\t"
        "adc	x20, x20, xzr\n\t"
        /* Sub */
        "subs	x12, x8, x4\n\t"
        "sbcs	x13, x9, x5\n\t"
        "sbcs	x14, x10, x6\n\t"
        "sbcs	x15, x11, x7\n\t"
        "csetm	x28, cc\n\t"
        "mov	x25, #-19\n\t"
        "extr	x28, x28, x15, #63\n\t"
        "mul	x25, x28, x25\n\t"
        /*   Add modulus (if underflow) */
        "subs	x12, x12, x25\n\t"
        "sbcs	x13, x13, xzr\n\t"
        "and	x15, x15, #0x7fffffffffffffff\n\t"
        "sbcs	x14, x14, xzr\n\t"
        "sbc	x15, x15, xzr\n\t"
        "ldr	x2, [x29, #32]\n\t"
        "add	x2, x2, #32\n\t"
        "mov	x1, x0\n\t"
        /* Multiply */
        "ldp	x8, x9, [x2]\n\t"
        "ldp	x10, x11, [x2, #16]\n\t"
        /* A[0] * B[0] */
        "umulh	x22, x16, x8\n\t"
        "mul	x21, x16, x8\n\t"
        /* A[2] * B[0] */
        "umulh	x24, x19, x8\n\t"
        "mul	x23, x19, x8\n\t"
        /* A[1] * B[0] */
        "mul	x25, x17, x8\n\t"
        "adds	x22, x22, x25\n\t"
        "umulh	x26, x17, x8\n\t"
        "adcs	x23, x23, x26\n\t"
        /* A[1] * B[3] */
        "umulh	x5, x17, x11\n\t"
        "adc	x24, x24, xzr\n\t"
        "mul	x4, x17, x11\n\t"
        /* A[0] * B[1] */
        "mul	x25, x16, x9\n\t"
        "adds	x22, x22, x25\n\t"
        "umulh	x26, x16, x9\n\t"
        "adcs	x23, x23, x26\n\t"
        /* A[2] * B[1] */
        "mul	x25, x19, x9\n\t"
        "adcs	x24, x24, x25\n\t"
        "umulh	x26, x19, x9\n\t"
        "adcs	x4, x4, x26\n\t"
        "adc	x5, x5, xzr\n\t"
        /* A[1] * B[2] */
        "mul	x25, x17, x10\n\t"
        "adds	x24, x24, x25\n\t"
        "umulh	x26, x17, x10\n\t"
        "adcs	x4, x4, x26\n\t"
        "adcs	x5, x5, xzr\n\t"
        "adc	x6, xzr, xzr\n\t"
        /* A[0] * B[2] */
        "mul	x25, x16, x10\n\t"
        "adds	x23, x23, x25\n\t"
        "umulh	x26, x16, x10\n\t"
        "adcs	x24, x24, x26\n\t"
        "adcs	x4, x4, xzr\n\t"
        "adcs	x5, x5, xzr\n\t"
        "adc	x6, x6, xzr\n\t"
        /* A[1] * B[1] */
        "mul	x25, x17, x9\n\t"
        "adds	x23, x23, x25\n\t"
        "umulh	x26, x17, x9\n\t"
        "adcs	x24, x24, x26\n\t"
        /* A[3] * B[1] */
        "mul	x25, x20, x9\n\t"
        "adcs	x4, x4, x25\n\t"
        "umulh	x26, x20, x9\n\t"
        "adcs	x5, x5, x26\n\t"
        "adc	x6, x6, xzr\n\t"
        /* A[2] * B[2] */
        "mul	x25, x19, x10\n\t"
        "adds	x4, x4, x25\n\t"
        "umulh	x26, x19, x10\n\t"
        "adcs	x5, x5, x26\n\t"
        /* A[3] * B[3] */
        "mul	x25, x20, x11\n\t"
        "adcs	x6, x6, x25\n\t"
        "umulh	x7, x20, x11\n\t"
        "adc	x7, x7, xzr\n\t"
        /* A[0] * B[3] */
        "mul	x25, x16, x11\n\t"
        "adds	x24, x24, x25\n\t"
        "umulh	x26, x16, x11\n\t"
        "adcs	x4, x4, x26\n\t"
        /* A[2] * B[3] */
        "mul	x25, x19, x11\n\t"
        "adcs	x5, x5, x25\n\t"
        "umulh	x26, x19, x11\n\t"
        "adcs	x6, x6, x26\n\t"
        "adc	x7, x7, xzr\n\t"
        /* A[3] * B[0] */
        "mul	x25, x20, x8\n\t"
        "adds	x24, x24, x25\n\t"
        "umulh	x26, x20, x8\n\t"
        "adcs	x4, x4, x26\n\t"
        /* A[3] * B[2] */
        "mul	x25, x20, x10\n\t"
        "adcs	x5, x5, x25\n\t"
        "umulh	x26, x20, x10\n\t"
        "adcs	x6, x6, x26\n\t"
        "adc	x7, x7, xzr\n\t"
        /* Reduce */
        "mov	x25, #38\n\t"
        "mul	x26, x25, x7\n\t"
        "adds	x24, x24, x26\n\t"
        "umulh	x27, x25, x7\n\t"
        "adc	x27, x27, xzr\n\t"
        "mov	x25, #19\n\t"
        "extr	x27, x27, x24, #63\n\t"
        "mul	x27, x27, x25\n\t"
        "and	x24, x24, #0x7fffffffffffffff\n\t"
        "mov	x25, #38\n\t"
        "mul	x26, x25, x4\n\t"
        "adds	x21, x21, x26\n\t"
        "umulh	x4, x25, x4\n\t"
        "mul	x26, x25, x5\n\t"
        "adcs	x22, x22, x26\n\t"
        "umulh	x5, x25, x5\n\t"
        "mul	x26, x25, x6\n\t"
        "adcs	x23, x23, x26\n\t"
        "umulh	x6, x25, x6\n\t"
        "adc	x24, x24, xzr\n\t"
        /*  Add high product results in */
        "adds	x21, x21, x27\n\t"
        "adcs	x22, x22, x4\n\t"
        "adcs	x23, x23, x5\n\t"
        "adc	x24, x24, x6\n\t"
        "sub	x2, x2, #32\n\t"
        "add	x1, x0, #32\n\t"
        "add	x0, x0, #32\n\t"
        /* Multiply */
        "ldp	x16, x17, [x2]\n\t"
        "ldp	x19, x20, [x2, #16]\n\t"
        /* A[0] * B[0] */
        "umulh	x5, x12, x16\n\t"
        "mul	x4, x12, x16\n\t"
        /* A[2] * B[0] */
        "umulh	x7, x14, x16\n\t"
        "mul	x6, x14, x16\n\t"
        /* A[1] * B[0] */
        "mul	x25, x13, x16\n\t"
        "adds	x5, x5, x25\n\t"
        "umulh	x26, x13, x16\n\t"
        "adcs	x6, x6, x26\n\t"
        /* A[1] * B[3] */
        "umulh	x9, x13, x20\n\t"
        "adc	x7, x7, xzr\n\t"
        "mul	x8, x13, x20\n\t"
        /* A[0] * B[1] */
        "mul	x25, x12, x17\n\t"
        "adds	x5, x5, x25\n\t"
        "umulh	x26, x12, x17\n\t"
        "adcs	x6, x6, x26\n\t"
        /* A[2] * B[1] */
        "mul	x25, x14, x17\n\t"
        "adcs	x7, x7, x25\n\t"
        "umulh	x26, x14, x17\n\t"
        "adcs	x8, x8, x26\n\t"
        "adc	x9, x9, xzr\n\t"
        /* A[1] * B[2] */
        "mul	x25, x13, x19\n\t"
        "adds	x7, x7, x25\n\t"
        "umulh	x26, x13, x19\n\t"
        "adcs	x8, x8, x26\n\t"
        "adcs	x9, x9, xzr\n\t"
        "adc	x10, xzr, xzr\n\t"
        /* A[0] * B[2] */
        "mul	x25, x12, x19\n\t"
        "adds	x6, x6, x25\n\t"
        "umulh	x26, x12, x19\n\t"
        "adcs	x7, x7, x26\n\t"
        "adcs	x8, x8, xzr\n\t"
        "adcs	x9, x9, xzr\n\t"
        "adc	x10, x10, xzr\n\t"
        /* A[1] * B[1] */
        "mul	x25, x13, x17\n\t"
        "adds	x6, x6, x25\n\t"
        "umulh	x26, x13, x17\n\t"
        "adcs	x7, x7, x26\n\t"
        /* A[3] * B[1] */
        "mul	x25, x15, x17\n\t"
        "adcs	x8, x8, x25\n\t"
        "umulh	x26, x15, x17\n\t"
        "adcs	x9, x9, x26\n\t"
        "adc	x10, x10, xzr\n\t"
        /* A[2] * B[2] */
        "mul	x25, x14, x19\n\t"
        "adds	x8, x8, x25\n\t"
        "umulh	x26, x14, x19\n\t"
        "adcs	x9, x9, x26\n\t"
        /* A[3] * B[3] */
        "mul	x25, x15, x20\n\t"
        "adcs	x10, x10, x25\n\t"
        "umulh	x11, x15, x20\n\t"
        "adc	x11, x11, xzr\n\t"
        /* A[0] * B[3] */
        "mul	x25, x12, x20\n\t"
        "adds	x7, x7, x25\n\t"
        "umulh	x26, x12, x20\n\t"
        "adcs	x8, x8, x26\n\t"
        /* A[2] * B[3] */
        "mul	x25, x14, x20\n\t"
        "adcs	x9, x9, x25\n\t"
        "umulh	x26, x14, x20\n\t"
        "adcs	x10, x10, x26\n\t"
        "adc	x11, x11, xzr\n\t"
        /* A[3] * B[0] */
        "mul	x25, x15, x16\n\t"
        "adds	x7, x7, x25\n\t"
        "umulh	x26, x15, x16\n\t"
        "adcs	x8, x8, x26\n\t"
        /* A[3] * B[2] */
        "mul	x25, x15, x19\n\t"
        "adcs	x9, x9, x25\n\t"
        "umulh	x26, x15, x19\n\t"
        "adcs	x10, x10, x26\n\t"
        "adc	x11, x11, xzr\n\t"
        /* Reduce */
        "mov	x25, #38\n\t"
        "mul	x26, x25, x11\n\t"
        "adds	x7, x7, x26\n\t"
        "umulh	x27, x25, x11\n\t"
        "adc	x27, x27, xzr\n\t"
        "mov	x25, #19\n\t"
        "extr	x27, x27, x7, #63\n\t"
        "mul	x27, x27, x25\n\t"
        "and	x7, x7, #0x7fffffffffffffff\n\t"
        "mov	x25, #38\n\t"
        "mul	x26, x25, x8\n\t"
        "adds	x4, x4, x26\n\t"
        "umulh	x8, x25, x8\n\t"
        "mul	x26, x25, x9\n\t"
        "adcs	x5, x5, x26\n\t"
        "umulh	x9, x25, x9\n\t"
        "mul	x26, x25, x10\n\t"
        "adcs	x6, x6, x26\n\t"
        "umulh	x10, x25, x10\n\t"
        "adc	x7, x7, xzr\n\t"
        /*  Add high product results in */
        "adds	x4, x4, x27\n\t"
        "adcs	x5, x5, x8\n\t"
        "adcs	x6, x6, x9\n\t"
        "adc	x7, x7, x10\n\t"
        "mov	x3, x0\n\t"
        "sub	x2, x0, #32\n\t"
        "sub	x1, x0, #32\n\t"
        /* Add */
        "adds	x8, x21, x4\n\t"
        "adcs	x9, x22, x5\n\t"
        "adcs	x10, x23, x6\n\t"
        "adcs	x11, x24, x7\n\t"
        "cset	x28, cs\n\t"
        "mov	x25, #19\n\t"
        "extr	x28, x28, x11, #63\n\t"
        "mul	x25, x28, x25\n\t"
        /*   Sub modulus (if overflow) */
        "adds	x8, x8, x25\n\t"
        "adcs	x9, x9, xzr\n\t"
        "and	x11, x11, #0x7fffffffffffffff\n\t"
        "adcs	x10, x10, xzr\n\t"
        "adc	x11, x11, xzr\n\t"
        /* Sub */
        "subs	x12, x21, x4\n\t"
        "sbcs	x13, x22, x5\n\t"
        "sbcs	x14, x23, x6\n\t"
        "sbcs	x15, x24, x7\n\t"
        "csetm	x28, cc\n\t"
        "mov	x25, #-19\n\t"
        "extr	x28, x28, x15, #63\n\t"
        "mul	x25, x28, x25\n\t"
        /*   Add modulus (if underflow) */
        "subs	x12, x12, x25\n\t"
        "sbcs	x13, x13, xzr\n\t"
        "and	x15, x15, #0x7fffffffffffffff\n\t"
        "sbcs	x14, x14, xzr\n\t"
        "sbc	x15, x15, xzr\n\t"
        "stp	x8, x9, [x0]\n\t"
        "stp	x10, x11, [x0, #16]\n\t"
        "stp	x12, x13, [x1]\n\t"
        "stp	x14, x15, [x1, #16]\n\t"
        "ldr	x1, [x29, #24]\n\t"
        "ldr	x2, [x29, #32]\n\t"
        "add	x2, x2, #0x40\n\t"
        "add	x1, x1, #0x60\n\t"
        "add	x0, x0, #0x40\n\t"
        /* Multiply */
        "ldp	x21, x22, [x1]\n\t"
        "ldp	x23, x24, [x1, #16]\n\t"
        "ldp	x4, x5, [x2]\n\t"
        "ldp	x6, x7, [x2, #16]\n\t"
        /* A[0] * B[0] */
        "umulh	x17, x21, x4\n\t"
        "mul	x16, x21, x4\n\t"
        /* A[2] * B[0] */
        "umulh	x20, x23, x4\n\t"
        "mul	x19, x23, x4\n\t"
        /* A[1] * B[0] */
        "mul	x25, x22, x4\n\t"
        "adds	x17, x17, x25\n\t"
        "umulh	x26, x22, x4\n\t"
        "adcs	x19, x19, x26\n\t"
        /* A[1] * B[3] */
        "umulh	x9, x22, x7\n\t"
        "adc	x20, x20, xzr\n\t"
        "mul	x8, x22, x7\n\t"
        /* A[0] * B[1] */
        "mul	x25, x21, x5\n\t"
        "adds	x17, x17, x25\n\t"
        "umulh	x26, x21, x5\n\t"
        "adcs	x19, x19, x26\n\t"
        /* A[2] * B[1] */
        "mul	x25, x23, x5\n\t"
        "adcs	x20, x20, x25\n\t"
        "umulh	x26, x23, x5\n\t"
        "adcs	x8, x8, x26\n\t"
        "adc	x9, x9, xzr\n\t"
        /* A[1] * B[2] */
        "mul	x25, x22, x6\n\t"
        "adds	x20, x20, x25\n\t"
        "umulh	x26, x22, x6\n\t"
        "adcs	x8, x8, x26\n\t"
        "adcs	x9, x9, xzr\n\t"
        "adc	x10, xzr, xzr\n\t"
        /* A[0] * B[2] */
        "mul	x25, x21, x6\n\t"
        "adds	x19, x19, x25\n\t"
        "umulh	x26, x21, x6\n\t"
        "adcs	x20, x20, x26\n\t"
        "adcs	x8, x8, xzr\n\t"
        "adcs	x9, x9, xzr\n\t"
        "adc	x10, x10, xzr\n\t"
        /* A[1] * B[1] */
        "mul	x25, x22, x5\n\t"
        "adds	x19, x19, x25\n\t"
        "umulh	x26, x22, x5\n\t"
        "adcs	x20, x20, x26\n\t"
        /* A[3] * B[1] */
        "mul	x25, x24, x5\n\t"
        "adcs	x8, x8, x25\n\t"
        "umulh	x26, x24, x5\n\t"
        "adcs	x9, x9, x26\n\t"
        "adc	x10, x10, xzr\n\t"
        /* A[2] * B[2] */
        "mul	x25, x23, x6\n\t"
        "adds	x8, x8, x25\n\t"
        "umulh	x26, x23, x6\n\t"
        "adcs	x9, x9, x26\n\t"
        /* A[3] * B[3] */
        "mul	x25, x24, x7\n\t"
        "adcs	x10, x10, x25\n\t"
        "umulh	x11, x24, x7\n\t"
        "adc	x11, x11, xzr\n\t"
        /* A[0] * B[3] */
        "mul	x25, x21, x7\n\t"
        "adds	x20, x20, x25\n\t"
        "umulh	x26, x21, x7\n\t"
        "adcs	x8, x8, x26\n\t"
        /* A[2] * B[3] */
        "mul	x25, x23, x7\n\t"
        "adcs	x9, x9, x25\n\t"
        "umulh	x26, x23, x7\n\t"
        "adcs	x10, x10, x26\n\t"
        "adc	x11, x11, xzr\n\t"
        /* A[3] * B[0] */
        "mul	x25, x24, x4\n\t"
        "adds	x20, x20, x25\n\t"
        "umulh	x26, x24, x4\n\t"
        "adcs	x8, x8, x26\n\t"
        /* A[3] * B[2] */
        "mul	x25, x24, x6\n\t"
        "adcs	x9, x9, x25\n\t"
        "umulh	x26, x24, x6\n\t"
        "adcs	x10, x10, x26\n\t"
        "adc	x11, x11, xzr\n\t"
        /* Reduce */
        "mov	x25, #38\n\t"
        "mul	x26, x25, x11\n\t"
        "adds	x20, x20, x26\n\t"
        "umulh	x27, x25, x11\n\t"
        "adc	x27, x27, xzr\n\t"
        "mov	x25, #19\n\t"
        "extr	x27, x27, x20, #63\n\t"
        "mul	x27, x27, x25\n\t"
        "and	x20, x20, #0x7fffffffffffffff\n\t"
        "mov	x25, #38\n\t"
        "mul	x26, x25, x8\n\t"
        "adds	x16, x16, x26\n\t"
        "umulh	x8, x25, x8\n\t"
        "mul	x26, x25, x9\n\t"
        "adcs	x17, x17, x26\n\t"
        "umulh	x9, x25, x9\n\t"
        "mul	x26, x25, x10\n\t"
        "adcs	x19, x19, x26\n\t"
        "umulh	x10, x25, x10\n\t"
        "adc	x20, x20, xzr\n\t"
        /*  Add high product results in */
        "adds	x16, x16, x27\n\t"
        "adcs	x17, x17, x8\n\t"
        "adcs	x19, x19, x9\n\t"
        "adc	x20, x20, x10\n\t"
        "sub	x1, x1, #32\n\t"
        /* Double */
        "ldp	x12, x13, [x1]\n\t"
        "ldp	x14, x15, [x1, #16]\n\t"
        "adds	x12, x12, x12\n\t"
        "adcs	x13, x13, x13\n\t"
        "adcs	x14, x14, x14\n\t"
        "adc	x15, x15, x15\n\t"
        "mov	x25, #-19\n\t"
        "asr	x28, x15, #63\n\t"
        /*   Mask the modulus */
        "and	x25, x28, x25\n\t"
        "and	x26, x28, #0x7fffffffffffffff\n\t"
        /*   Sub modulus (if overflow) */
        "subs	x12, x12, x25\n\t"
        "sbcs	x13, x13, x28\n\t"
        "sbcs	x14, x14, x28\n\t"
        "sbc	x15, x15, x26\n\t"
        "mov	x3, x0\n\t"
        "sub	x2, x0, #32\n\t"
        "sub	x1, x0, #32\n\t"
        /* Add */
        "adds	x8, x12, x16\n\t"
        "adcs	x9, x13, x17\n\t"
        "adcs	x10, x14, x19\n\t"
        "adcs	x11, x15, x20\n\t"
        "cset	x28, cs\n\t"
        "mov	x25, #19\n\t"
        "extr	x28, x28, x11, #63\n\t"
        "mul	x25, x28, x25\n\t"
        /*   Sub modulus (if overflow) */
        "adds	x8, x8, x25\n\t"
        "adcs	x9, x9, xzr\n\t"
        "and	x11, x11, #0x7fffffffffffffff\n\t"
        "adcs	x10, x10, xzr\n\t"
        "adc	x11, x11, xzr\n\t"
        /* Sub */
        "subs	x4, x12, x16\n\t"
        "sbcs	x5, x13, x17\n\t"
        "sbcs	x6, x14, x19\n\t"
        "sbcs	x7, x15, x20\n\t"
        "csetm	x28, cc\n\t"
        "mov	x25, #-19\n\t"
        "extr	x28, x28, x7, #63\n\t"
        "mul	x25, x28, x25\n\t"
        /*   Add modulus (if underflow) */
        "subs	x4, x4, x25\n\t"
        "sbcs	x5, x5, xzr\n\t"
        "and	x7, x7, #0x7fffffffffffffff\n\t"
        "sbcs	x6, x6, xzr\n\t"
        "sbc	x7, x7, xzr\n\t"
        "stp	x8, x9, [x0]\n\t"
        "stp	x10, x11, [x0, #16]\n\t"
        "stp	x4, x5, [x1]\n\t"
        "stp	x6, x7, [x1, #16]\n\t"
        "ldp	x29, x30, [sp], #48\n\t"
        : [r] "+r" (r)
        : [p] "r" (p), [q] "r" (q)
        : "memory", "cc", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10",
            "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20",
            "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28"
    );
}

void ge_add(ge_p1p1* r, const ge_p3* p, const ge_cached* q)
{
    __asm__ __volatile__ (
        "stp	x29, x30, [sp, #-48]!\n\t"
        "add	x29, sp, #0\n\t"
        "str	%x[r], [x29, #16]\n\t"
        "str	%x[p], [x29, #24]\n\t"
        "str	%x[q], [x29, #32]\n\t"
        "mov	x3, x1\n\t"
        "add	x2, x1, #32\n\t"
        "add	x1, x0, #32\n\t"
        /* Add */
        "ldp	x8, x9, [x2]\n\t"
        "ldp	x10, x11, [x2, #16]\n\t"
        "ldp	x4, x5, [x3]\n\t"
        "ldp	x6, x7, [x3, #16]\n\t"
        "adds	x16, x8, x4\n\t"
        "adcs	x17, x9, x5\n\t"
        "adcs	x19, x10, x6\n\t"
        "adcs	x20, x11, x7\n\t"
        "cset	x28, cs\n\t"
        "mov	x25, #19\n\t"
        "extr	x28, x28, x20, #63\n\t"
        "mul	x25, x28, x25\n\t"
        /*   Sub modulus (if overflow) */
        "adds	x16, x16, x25\n\t"
        "adcs	x17, x17, xzr\n\t"
        "and	x20, x20, #0x7fffffffffffffff\n\t"
        "adcs	x19, x19, xzr\n\t"
        "adc	x20, x20, xzr\n\t"
        /* Sub */
        "subs	x12, x8, x4\n\t"
        "sbcs	x13, x9, x5\n\t"
        "sbcs	x14, x10, x6\n\t"
        "sbcs	x15, x11, x7\n\t"
        "csetm	x28, cc\n\t"
        "mov	x25, #-19\n\t"
        "extr	x28, x28, x15, #63\n\t"
        "mul	x25, x28, x25\n\t"
        /*   Add modulus (if underflow) */
        "subs	x12, x12, x25\n\t"
        "sbcs	x13, x13, xzr\n\t"
        "and	x15, x15, #0x7fffffffffffffff\n\t"
        "sbcs	x14, x14, xzr\n\t"
        "sbc	x15, x15, xzr\n\t"
        "ldr	x2, [x29, #32]\n\t"
        "mov	x1, x0\n\t"
        /* Multiply */
        "ldp	x8, x9, [x2]\n\t"
        "ldp	x10, x11, [x2, #16]\n\t"
        /* A[0] * B[0] */
        "umulh	x22, x16, x8\n\t"
        "mul	x21, x16, x8\n\t"
        /* A[2] * B[0] */
        "umulh	x24, x19, x8\n\t"
        "mul	x23, x19, x8\n\t"
        /* A[1] * B[0] */
        "mul	x25, x17, x8\n\t"
        "adds	x22, x22, x25\n\t"
        "umulh	x26, x17, x8\n\t"
        "adcs	x23, x23, x26\n\t"
        /* A[1] * B[3] */
        "umulh	x5, x17, x11\n\t"
        "adc	x24, x24, xzr\n\t"
        "mul	x4, x17, x11\n\t"
        /* A[0] * B[1] */
        "mul	x25, x16, x9\n\t"
        "adds	x22, x22, x25\n\t"
        "umulh	x26, x16, x9\n\t"
        "adcs	x23, x23, x26\n\t"
        /* A[2] * B[1] */
        "mul	x25, x19, x9\n\t"
        "adcs	x24, x24, x25\n\t"
        "umulh	x26, x19, x9\n\t"
        "adcs	x4, x4, x26\n\t"
        "adc	x5, x5, xzr\n\t"
        /* A[1] * B[2] */
        "mul	x25, x17, x10\n\t"
        "adds	x24, x24, x25\n\t"
        "umulh	x26, x17, x10\n\t"
        "adcs	x4, x4, x26\n\t"
        "adcs	x5, x5, xzr\n\t"
        "adc	x6, xzr, xzr\n\t"
        /* A[0] * B[2] */
        "mul	x25, x16, x10\n\t"
        "adds	x23, x23, x25\n\t"
        "umulh	x26, x16, x10\n\t"
        "adcs	x24, x24, x26\n\t"
        "adcs	x4, x4, xzr\n\t"
        "adcs	x5, x5, xzr\n\t"
        "adc	x6, x6, xzr\n\t"
        /* A[1] * B[1] */
        "mul	x25, x17, x9\n\t"
        "adds	x23, x23, x25\n\t"
        "umulh	x26, x17, x9\n\t"
        "adcs	x24, x24, x26\n\t"
        /* A[3] * B[1] */
        "mul	x25, x20, x9\n\t"
        "adcs	x4, x4, x25\n\t"
        "umulh	x26, x20, x9\n\t"
        "adcs	x5, x5, x26\n\t"
        "adc	x6, x6, xzr\n\t"
        /* A[2] * B[2] */
        "mul	x25, x19, x10\n\t"
        "adds	x4, x4, x25\n\t"
        "umulh	x26, x19, x10\n\t"
        "adcs	x5, x5, x26\n\t"
        /* A[3] * B[3] */
        "mul	x25, x20, x11\n\t"
        "adcs	x6, x6, x25\n\t"
        "umulh	x7, x20, x11\n\t"
        "adc	x7, x7, xzr\n\t"
        /* A[0] * B[3] */
        "mul	x25, x16, x11\n\t"
        "adds	x24, x24, x25\n\t"
        "umulh	x26, x16, x11\n\t"
        "adcs	x4, x4, x26\n\t"
        /* A[2] * B[3] */
        "mul	x25, x19, x11\n\t"
        "adcs	x5, x5, x25\n\t"
        "umulh	x26, x19, x11\n\t"
        "adcs	x6, x6, x26\n\t"
        "adc	x7, x7, xzr\n\t"
        /* A[3] * B[0] */
        "mul	x25, x20, x8\n\t"
        "adds	x24, x24, x25\n\t"
        "umulh	x26, x20, x8\n\t"
        "adcs	x4, x4, x26\n\t"
        /* A[3] * B[2] */
        "mul	x25, x20, x10\n\t"
        "adcs	x5, x5, x25\n\t"
        "umulh	x26, x20, x10\n\t"
        "adcs	x6, x6, x26\n\t"
        "adc	x7, x7, xzr\n\t"
        /* Reduce */
        "mov	x25, #38\n\t"
        "mul	x26, x25, x7\n\t"
        "adds	x24, x24, x26\n\t"
        "umulh	x27, x25, x7\n\t"
        "adc	x27, x27, xzr\n\t"
        "mov	x25, #19\n\t"
        "extr	x27, x27, x24, #63\n\t"
        "mul	x27, x27, x25\n\t"
        "and	x24, x24, #0x7fffffffffffffff\n\t"
        "mov	x25, #38\n\t"
        "mul	x26, x25, x4\n\t"
        "adds	x21, x21, x26\n\t"
        "umulh	x4, x25, x4\n\t"
        "mul	x26, x25, x5\n\t"
        "adcs	x22, x22, x26\n\t"
        "umulh	x5, x25, x5\n\t"
        "mul	x26, x25, x6\n\t"
        "adcs	x23, x23, x26\n\t"
        "umulh	x6, x25, x6\n\t"
        "adc	x24, x24, xzr\n\t"
        /*  Add high product results in */
        "adds	x21, x21, x27\n\t"
        "adcs	x22, x22, x4\n\t"
        "adcs	x23, x23, x5\n\t"
        "adc	x24, x24, x6\n\t"
        /* Store */
        "stp	x21, x22, [x0]\n\t"
        "stp	x23, x24, [x0, #16]\n\t"
        "add	x2, x2, #32\n\t"
        "add	x1, x0, #32\n\t"
        "add	x0, x0, #32\n\t"
        /* Multiply */
        "ldp	x16, x17, [x2]\n\t"
        "ldp	x19, x20, [x2, #16]\n\t"
        /* A[0] * B[0] */
        "umulh	x5, x12, x16\n\t"
        "mul	x4, x12, x16\n\t"
        /* A[2] * B[0] */
        "umulh	x7, x14, x16\n\t"
        "mul	x6, x14, x16\n\t"
        /* A[1] * B[0] */
        "mul	x25, x13, x16\n\t"
        "adds	x5, x5, x25\n\t"
        "umulh	x26, x13, x16\n\t"
        "adcs	x6, x6, x26\n\t"
        /* A[1] * B[3] */
        "umulh	x9, x13, x20\n\t"
        "adc	x7, x7, xzr\n\t"
        "mul	x8, x13, x20\n\t"
        /* A[0] * B[1] */
        "mul	x25, x12, x17\n\t"
        "adds	x5, x5, x25\n\t"
        "umulh	x26, x12, x17\n\t"
        "adcs	x6, x6, x26\n\t"
        /* A[2] * B[1] */
        "mul	x25, x14, x17\n\t"
        "adcs	x7, x7, x25\n\t"
        "umulh	x26, x14, x17\n\t"
        "adcs	x8, x8, x26\n\t"
        "adc	x9, x9, xzr\n\t"
        /* A[1] * B[2] */
        "mul	x25, x13, x19\n\t"
        "adds	x7, x7, x25\n\t"
        "umulh	x26, x13, x19\n\t"
        "adcs	x8, x8, x26\n\t"
        "adcs	x9, x9, xzr\n\t"
        "adc	x10, xzr, xzr\n\t"
        /* A[0] * B[2] */
        "mul	x25, x12, x19\n\t"
        "adds	x6, x6, x25\n\t"
        "umulh	x26, x12, x19\n\t"
        "adcs	x7, x7, x26\n\t"
        "adcs	x8, x8, xzr\n\t"
        "adcs	x9, x9, xzr\n\t"
        "adc	x10, x10, xzr\n\t"
        /* A[1] * B[1] */
        "mul	x25, x13, x17\n\t"
        "adds	x6, x6, x25\n\t"
        "umulh	x26, x13, x17\n\t"
        "adcs	x7, x7, x26\n\t"
        /* A[3] * B[1] */
        "mul	x25, x15, x17\n\t"
        "adcs	x8, x8, x25\n\t"
        "umulh	x26, x15, x17\n\t"
        "adcs	x9, x9, x26\n\t"
        "adc	x10, x10, xzr\n\t"
        /* A[2] * B[2] */
        "mul	x25, x14, x19\n\t"
        "adds	x8, x8, x25\n\t"
        "umulh	x26, x14, x19\n\t"
        "adcs	x9, x9, x26\n\t"
        /* A[3] * B[3] */
        "mul	x25, x15, x20\n\t"
        "adcs	x10, x10, x25\n\t"
        "umulh	x11, x15, x20\n\t"
        "adc	x11, x11, xzr\n\t"
        /* A[0] * B[3] */
        "mul	x25, x12, x20\n\t"
        "adds	x7, x7, x25\n\t"
        "umulh	x26, x12, x20\n\t"
        "adcs	x8, x8, x26\n\t"
        /* A[2] * B[3] */
        "mul	x25, x14, x20\n\t"
        "adcs	x9, x9, x25\n\t"
        "umulh	x26, x14, x20\n\t"
        "adcs	x10, x10, x26\n\t"
        "adc	x11, x11, xzr\n\t"
        /* A[3] * B[0] */
        "mul	x25, x15, x16\n\t"
        "adds	x7, x7, x25\n\t"
        "umulh	x26, x15, x16\n\t"
        "adcs	x8, x8, x26\n\t"
        /* A[3] * B[2] */
        "mul	x25, x15, x19\n\t"
        "adcs	x9, x9, x25\n\t"
        "umulh	x26, x15, x19\n\t"
        "adcs	x10, x10, x26\n\t"
        "adc	x11, x11, xzr\n\t"
        /* Reduce */
        "mov	x25, #38\n\t"
        "mul	x26, x25, x11\n\t"
        "adds	x7, x7, x26\n\t"
        "umulh	x27, x25, x11\n\t"
        "adc	x27, x27, xzr\n\t"
        "mov	x25, #19\n\t"
        "extr	x27, x27, x7, #63\n\t"
        "mul	x27, x27, x25\n\t"
        "and	x7, x7, #0x7fffffffffffffff\n\t"
        "mov	x25, #38\n\t"
        "mul	x26, x25, x8\n\t"
        "adds	x4, x4, x26\n\t"
        "umulh	x8, x25, x8\n\t"
        "mul	x26, x25, x9\n\t"
        "adcs	x5, x5, x26\n\t"
        "umulh	x9, x25, x9\n\t"
        "mul	x26, x25, x10\n\t"
        "adcs	x6, x6, x26\n\t"
        "umulh	x10, x25, x10\n\t"
        "adc	x7, x7, xzr\n\t"
        /*  Add high product results in */
        "adds	x4, x4, x27\n\t"
        "adcs	x5, x5, x8\n\t"
        "adcs	x6, x6, x9\n\t"
        "adc	x7, x7, x10\n\t"
        /* Store */
        "stp	x4, x5, [x0]\n\t"
        "stp	x6, x7, [x0, #16]\n\t"
        "mov	x3, x0\n\t"
        "sub	x2, x0, #32\n\t"
        "sub	x1, x0, #32\n\t"
        /* Add */
        "adds	x8, x21, x4\n\t"
        "adcs	x9, x22, x5\n\t"
        "adcs	x10, x23, x6\n\t"
        "adcs	x11, x24, x7\n\t"
        "cset	x28, cs\n\t"
        "mov	x25, #19\n\t"
        "extr	x28, x28, x11, #63\n\t"
        "mul	x25, x28, x25\n\t"
        /*   Sub modulus (if overflow) */
        "adds	x8, x8, x25\n\t"
        "adcs	x9, x9, xzr\n\t"
        "and	x11, x11, #0x7fffffffffffffff\n\t"
        "adcs	x10, x10, xzr\n\t"
        "adc	x11, x11, xzr\n\t"
        /* Sub */
        "subs	x12, x21, x4\n\t"
        "sbcs	x13, x22, x5\n\t"
        "sbcs	x14, x23, x6\n\t"
        "sbcs	x15, x24, x7\n\t"
        "csetm	x28, cc\n\t"
        "mov	x25, #-19\n\t"
        "extr	x28, x28, x15, #63\n\t"
        "mul	x25, x28, x25\n\t"
        /*   Add modulus (if underflow) */
        "subs	x12, x12, x25\n\t"
        "sbcs	x13, x13, xzr\n\t"
        "and	x15, x15, #0x7fffffffffffffff\n\t"
        "sbcs	x14, x14, xzr\n\t"
        "sbc	x15, x15, xzr\n\t"
        "stp	x8, x9, [x0]\n\t"
        "stp	x10, x11, [x0, #16]\n\t"
        "stp	x12, x13, [x1]\n\t"
        "stp	x14, x15, [x1, #16]\n\t"
        "ldr	x1, [x29, #24]\n\t"
        "ldr	x2, [x29, #32]\n\t"
        "add	x2, x2, #0x60\n\t"
        "add	x1, x1, #0x60\n\t"
        "add	x0, x0, #0x40\n\t"
        /* Multiply */
        "ldp	x21, x22, [x1]\n\t"
        "ldp	x23, x24, [x1, #16]\n\t"
        "ldp	x4, x5, [x2]\n\t"
        "ldp	x6, x7, [x2, #16]\n\t"
        /* A[0] * B[0] */
        "umulh	x17, x21, x4\n\t"
        "mul	x16, x21, x4\n\t"
        /* A[2] * B[0] */
        "umulh	x20, x23, x4\n\t"
        "mul	x19, x23, x4\n\t"
        /* A[1] * B[0] */
        "mul	x25, x22, x4\n\t"
        "adds	x17, x17, x25\n\t"
        "umulh	x26, x22, x4\n\t"
        "adcs	x19, x19, x26\n\t"
        /* A[1] * B[3] */
        "umulh	x9, x22, x7\n\t"
        "adc	x20, x20, xzr\n\t"
        "mul	x8, x22, x7\n\t"
        /* A[0] * B[1] */
        "mul	x25, x21, x5\n\t"
        "adds	x17, x17, x25\n\t"
        "umulh	x26, x21, x5\n\t"
        "adcs	x19, x19, x26\n\t"
        /* A[2] * B[1] */
        "mul	x25, x23, x5\n\t"
        "adcs	x20, x20, x25\n\t"
        "umulh	x26, x23, x5\n\t"
        "adcs	x8, x8, x26\n\t"
        "adc	x9, x9, xzr\n\t"
        /* A[1] * B[2] */
        "mul	x25, x22, x6\n\t"
        "adds	x20, x20, x25\n\t"
        "umulh	x26, x22, x6\n\t"
        "adcs	x8, x8, x26\n\t"
        "adcs	x9, x9, xzr\n\t"
        "adc	x10, xzr, xzr\n\t"
        /* A[0] * B[2] */
        "mul	x25, x21, x6\n\t"
        "adds	x19, x19, x25\n\t"
        "umulh	x26, x21, x6\n\t"
        "adcs	x20, x20, x26\n\t"
        "adcs	x8, x8, xzr\n\t"
        "adcs	x9, x9, xzr\n\t"
        "adc	x10, x10, xzr\n\t"
        /* A[1] * B[1] */
        "mul	x25, x22, x5\n\t"
        "adds	x19, x19, x25\n\t"
        "umulh	x26, x22, x5\n\t"
        "adcs	x20, x20, x26\n\t"
        /* A[3] * B[1] */
        "mul	x25, x24, x5\n\t"
        "adcs	x8, x8, x25\n\t"
        "umulh	x26, x24, x5\n\t"
        "adcs	x9, x9, x26\n\t"
        "adc	x10, x10, xzr\n\t"
        /* A[2] * B[2] */
        "mul	x25, x23, x6\n\t"
        "adds	x8, x8, x25\n\t"
        "umulh	x26, x23, x6\n\t"
        "adcs	x9, x9, x26\n\t"
        /* A[3] * B[3] */
        "mul	x25, x24, x7\n\t"
        "adcs	x10, x10, x25\n\t"
        "umulh	x11, x24, x7\n\t"
        "adc	x11, x11, xzr\n\t"
        /* A[0] * B[3] */
        "mul	x25, x21, x7\n\t"
        "adds	x20, x20, x25\n\t"
        "umulh	x26, x21, x7\n\t"
        "adcs	x8, x8, x26\n\t"
        /* A[2] * B[3] */
        "mul	x25, x23, x7\n\t"
        "adcs	x9, x9, x25\n\t"
        "umulh	x26, x23, x7\n\t"
        "adcs	x10, x10, x26\n\t"
        "adc	x11, x11, xzr\n\t"
        /* A[3] * B[0] */
        "mul	x25, x24, x4\n\t"
        "adds	x20, x20, x25\n\t"
        "umulh	x26, x24, x4\n\t"
        "adcs	x8, x8, x26\n\t"
        /* A[3] * B[2] */
        "mul	x25, x24, x6\n\t"
        "adcs	x9, x9, x25\n\t"
        "umulh	x26, x24, x6\n\t"
        "adcs	x10, x10, x26\n\t"
        "adc	x11, x11, xzr\n\t"
        /* Reduce */
        "mov	x25, #38\n\t"
        "mul	x26, x25, x11\n\t"
        "adds	x20, x20, x26\n\t"
        "umulh	x27, x25, x11\n\t"
        "adc	x27, x27, xzr\n\t"
        "mov	x25, #19\n\t"
        "extr	x27, x27, x20, #63\n\t"
        "mul	x27, x27, x25\n\t"
        "and	x20, x20, #0x7fffffffffffffff\n\t"
        "mov	x25, #38\n\t"
        "mul	x26, x25, x8\n\t"
        "adds	x16, x16, x26\n\t"
        "umulh	x8, x25, x8\n\t"
        "mul	x26, x25, x9\n\t"
        "adcs	x17, x17, x26\n\t"
        "umulh	x9, x25, x9\n\t"
        "mul	x26, x25, x10\n\t"
        "adcs	x19, x19, x26\n\t"
        "umulh	x10, x25, x10\n\t"
        "adc	x20, x20, xzr\n\t"
        /*  Add high product results in */
        "adds	x16, x16, x27\n\t"
        "adcs	x17, x17, x8\n\t"
        "adcs	x19, x19, x9\n\t"
        "adc	x20, x20, x10\n\t"
        /* Store */
        "stp	x16, x17, [x0]\n\t"
        "stp	x19, x20, [x0, #16]\n\t"
        "sub	x3, x2, #32\n\t"
        "sub	x2, x1, #32\n\t"
        "sub	x1, x0, #32\n\t"
        /* Multiply */
        "ldp	x4, x5, [x2]\n\t"
        "ldp	x6, x7, [x2, #16]\n\t"
        "ldp	x12, x13, [x3]\n\t"
        "ldp	x14, x15, [x3, #16]\n\t"
        /* A[0] * B[0] */
        "umulh	x9, x4, x12\n\t"
        "mul	x8, x4, x12\n\t"
        /* A[2] * B[0] */
        "umulh	x11, x6, x12\n\t"
        "mul	x10, x6, x12\n\t"
        /* A[1] * B[0] */
        "mul	x25, x5, x12\n\t"
        "adds	x9, x9, x25\n\t"
        "umulh	x26, x5, x12\n\t"
        "adcs	x10, x10, x26\n\t"
        /* A[1] * B[3] */
        "umulh	x17, x5, x15\n\t"
        "adc	x11, x11, xzr\n\t"
        "mul	x16, x5, x15\n\t"
        /* A[0] * B[1] */
        "mul	x25, x4, x13\n\t"
        "adds	x9, x9, x25\n\t"
        "umulh	x26, x4, x13\n\t"
        "adcs	x10, x10, x26\n\t"
        /* A[2] * B[1] */
        "mul	x25, x6, x13\n\t"
        "adcs	x11, x11, x25\n\t"
        "umulh	x26, x6, x13\n\t"
        "adcs	x16, x16, x26\n\t"
        "adc	x17, x17, xzr\n\t"
        /* A[1] * B[2] */
        "mul	x25, x5, x14\n\t"
        "adds	x11, x11, x25\n\t"
        "umulh	x26, x5, x14\n\t"
        "adcs	x16, x16, x26\n\t"
        "adcs	x17, x17, xzr\n\t"
        "adc	x19, xzr, xzr\n\t"
        /* A[0] * B[2] */
        "mul	x25, x4, x14\n\t"
        "adds	x10, x10, x25\n\t"
        "umulh	x26, x4, x14\n\t"
        "adcs	x11, x11, x26\n\t"
        "adcs	x16, x16, xzr\n\t"
        "adcs	x17, x17, xzr\n\t"
        "adc	x19, x19, xzr\n\t"
        /* A[1] * B[1] */
        "mul	x25, x5, x13\n\t"
        "adds	x10, x10, x25\n\t"
        "umulh	x26, x5, x13\n\t"
        "adcs	x11, x11, x26\n\t"
        /* A[3] * B[1] */
        "mul	x25, x7, x13\n\t"
        "adcs	x16, x16, x25\n\t"
        "umulh	x26, x7, x13\n\t"
        "adcs	x17, x17, x26\n\t"
        "adc	x19, x19, xzr\n\t"
        /* A[2] * B[2] */
        "mul	x25, x6, x14\n\t"
        "adds	x16, x16, x25\n\t"
        "umulh	x26, x6, x14\n\t"
        "adcs	x17, x17, x26\n\t"
        /* A[3] * B[3] */
        "mul	x25, x7, x15\n\t"
        "adcs	x19, x19, x25\n\t"
        "umulh	x20, x7, x15\n\t"
        "adc	x20, x20, xzr\n\t"
        /* A[0] * B[3] */
        "mul	x25, x4, x15\n\t"
        "adds	x11, x11, x25\n\t"
        "umulh	x26, x4, x15\n\t"
        "adcs	x16, x16, x26\n\t"
        /* A[2] * B[3] */
        "mul	x25, x6, x15\n\t"
        "adcs	x17, x17, x25\n\t"
        "umulh	x26, x6, x15\n\t"
        "adcs	x19, x19, x26\n\t"
        "adc	x20, x20, xzr\n\t"
        /* A[3] * B[0] */
        "mul	x25, x7, x12\n\t"
        "adds	x11, x11, x25\n\t"
        "umulh	x26, x7, x12\n\t"
        "adcs	x16, x16, x26\n\t"
        /* A[3] * B[2] */
        "mul	x25, x7, x14\n\t"
        "adcs	x17, x17, x25\n\t"
        "umulh	x26, x7, x14\n\t"
        "adcs	x19, x19, x26\n\t"
        "adc	x20, x20, xzr\n\t"
        /* Reduce */
        "mov	x25, #38\n\t"
        "mul	x26, x25, x20\n\t"
        "adds	x11, x11, x26\n\t"
        "umulh	x27, x25, x20\n\t"
        "adc	x27, x27, xzr\n\t"
        "mov	x25, #19\n\t"
        "extr	x27, x27, x11, #63\n\t"
        "mul	x27, x27, x25\n\t"
        "and	x11, x11, #0x7fffffffffffffff\n\t"
        "mov	x25, #38\n\t"
        "mul	x26, x25, x16\n\t"
        "adds	x8, x8, x26\n\t"
        "umulh	x16, x25, x16\n\t"
        "mul	x26, x25, x17\n\t"
        "adcs	x9, x9, x26\n\t"
        "umulh	x17, x25, x17\n\t"
        "mul	x26, x25, x19\n\t"
        "adcs	x10, x10, x26\n\t"
        "umulh	x19, x25, x19\n\t"
        "adc	x11, x11, xzr\n\t"
        /*  Add high product results in */
        "adds	x8, x8, x27\n\t"
        "adcs	x9, x9, x16\n\t"
        "adcs	x10, x10, x17\n\t"
        "adc	x11, x11, x19\n\t"
        /* Double */
        "adds	x8, x8, x8\n\t"
        "adcs	x9, x9, x9\n\t"
        "adcs	x10, x10, x10\n\t"
        "adc	x11, x11, x11\n\t"
        "mov	x25, #-19\n\t"
        "asr	x28, x11, #63\n\t"
        /*   Mask the modulus */
        "and	x25, x28, x25\n\t"
        "and	x26, x28, #0x7fffffffffffffff\n\t"
        /*   Sub modulus (if overflow) */
        "subs	x8, x8, x25\n\t"
        "sbcs	x9, x9, x28\n\t"
        "sbcs	x10, x10, x28\n\t"
        "sbc	x11, x11, x26\n\t"
        "mov	x3, x0\n\t"
        "sub	x2, x0, #32\n\t"
        "mov	x1, x0\n\t"
        "sub	x0, x0, #32\n\t"
        /* Add */
        "ldp	x4, x5, [x3]\n\t"
        "ldp	x6, x7, [x3, #16]\n\t"
        "adds	x21, x8, x4\n\t"
        "adcs	x22, x9, x5\n\t"
        "adcs	x23, x10, x6\n\t"
        "adcs	x24, x11, x7\n\t"
        "cset	x28, cs\n\t"
        "mov	x25, #19\n\t"
        "extr	x28, x28, x24, #63\n\t"
        "mul	x25, x28, x25\n\t"
        /*   Sub modulus (if overflow) */
        "adds	x21, x21, x25\n\t"
        "adcs	x22, x22, xzr\n\t"
        "and	x24, x24, #0x7fffffffffffffff\n\t"
        "adcs	x23, x23, xzr\n\t"
        "adc	x24, x24, xzr\n\t"
        /* Sub */
        "subs	x12, x8, x4\n\t"
        "sbcs	x13, x9, x5\n\t"
        "sbcs	x14, x10, x6\n\t"
        "sbcs	x15, x11, x7\n\t"
        "csetm	x28, cc\n\t"
        "mov	x25, #-19\n\t"
        "extr	x28, x28, x15, #63\n\t"
        "mul	x25, x28, x25\n\t"
        /*   Add modulus (if underflow) */
        "subs	x12, x12, x25\n\t"
        "sbcs	x13, x13, xzr\n\t"
        "and	x15, x15, #0x7fffffffffffffff\n\t"
        "sbcs	x14, x14, xzr\n\t"
        "sbc	x15, x15, xzr\n\t"
        "stp	x21, x22, [x0]\n\t"
        "stp	x23, x24, [x0, #16]\n\t"
        "stp	x12, x13, [x1]\n\t"
        "stp	x14, x15, [x1, #16]\n\t"
        "ldp	x29, x30, [sp], #48\n\t"
        : [r] "+r" (r)
        : [p] "r" (p), [q] "r" (q)
        : "memory", "cc", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10",
            "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20",
            "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28"
    );
}

void ge_sub(ge_p1p1* r, const ge_p3* p, const ge_cached* q)
{
    __asm__ __volatile__ (
        "stp	x29, x30, [sp, #-48]!\n\t"
        "add	x29, sp, #0\n\t"
        "str	%x[r], [x29, #16]\n\t"
        "str	%x[p], [x29, #24]\n\t"
        "str	%x[q], [x29, #32]\n\t"
        "mov	x3, x1\n\t"
        "add	x2, x1, #32\n\t"
        "add	x1, x0, #32\n\t"
        /* Add */
        "ldp	x8, x9, [x2]\n\t"
        "ldp	x10, x11, [x2, #16]\n\t"
        "ldp	x4, x5, [x3]\n\t"
        "ldp	x6, x7, [x3, #16]\n\t"
        "adds	x16, x8, x4\n\t"
        "adcs	x17, x9, x5\n\t"
        "adcs	x19, x10, x6\n\t"
        "adcs	x20, x11, x7\n\t"
        "cset	x28, cs\n\t"
        "mov	x25, #19\n\t"
        "extr	x28, x28, x20, #63\n\t"
        "mul	x25, x28, x25\n\t"
        /*   Sub modulus (if overflow) */
        "adds	x16, x16, x25\n\t"
        "adcs	x17, x17, xzr\n\t"
        "and	x20, x20, #0x7fffffffffffffff\n\t"
        "adcs	x19, x19, xzr\n\t"
        "adc	x20, x20, xzr\n\t"
        /* Sub */
        "subs	x12, x8, x4\n\t"
        "sbcs	x13, x9, x5\n\t"
        "sbcs	x14, x10, x6\n\t"
        "sbcs	x15, x11, x7\n\t"
        "csetm	x28, cc\n\t"
        "mov	x25, #-19\n\t"
        "extr	x28, x28, x15, #63\n\t"
        "mul	x25, x28, x25\n\t"
        /*   Add modulus (if underflow) */
        "subs	x12, x12, x25\n\t"
        "sbcs	x13, x13, xzr\n\t"
        "and	x15, x15, #0x7fffffffffffffff\n\t"
        "sbcs	x14, x14, xzr\n\t"
        "sbc	x15, x15, xzr\n\t"
        "ldr	x2, [x29, #32]\n\t"
        "add	x2, x2, #32\n\t"
        "mov	x1, x0\n\t"
        /* Multiply */
        "ldp	x8, x9, [x2]\n\t"
        "ldp	x10, x11, [x2, #16]\n\t"
        /* A[0] * B[0] */
        "umulh	x22, x16, x8\n\t"
        "mul	x21, x16, x8\n\t"
        /* A[2] * B[0] */
        "umulh	x24, x19, x8\n\t"
        "mul	x23, x19, x8\n\t"
        /* A[1] * B[0] */
        "mul	x25, x17, x8\n\t"
        "adds	x22, x22, x25\n\t"
        "umulh	x26, x17, x8\n\t"
        "adcs	x23, x23, x26\n\t"
        /* A[1] * B[3] */
        "umulh	x5, x17, x11\n\t"
        "adc	x24, x24, xzr\n\t"
        "mul	x4, x17, x11\n\t"
        /* A[0] * B[1] */
        "mul	x25, x16, x9\n\t"
        "adds	x22, x22, x25\n\t"
        "umulh	x26, x16, x9\n\t"
        "adcs	x23, x23, x26\n\t"
        /* A[2] * B[1] */
        "mul	x25, x19, x9\n\t"
        "adcs	x24, x24, x25\n\t"
        "umulh	x26, x19, x9\n\t"
        "adcs	x4, x4, x26\n\t"
        "adc	x5, x5, xzr\n\t"
        /* A[1] * B[2] */
        "mul	x25, x17, x10\n\t"
        "adds	x24, x24, x25\n\t"
        "umulh	x26, x17, x10\n\t"
        "adcs	x4, x4, x26\n\t"
        "adcs	x5, x5, xzr\n\t"
        "adc	x6, xzr, xzr\n\t"
        /* A[0] * B[2] */
        "mul	x25, x16, x10\n\t"
        "adds	x23, x23, x25\n\t"
        "umulh	x26, x16, x10\n\t"
        "adcs	x24, x24, x26\n\t"
        "adcs	x4, x4, xzr\n\t"
        "adcs	x5, x5, xzr\n\t"
        "adc	x6, x6, xzr\n\t"
        /* A[1] * B[1] */
        "mul	x25, x17, x9\n\t"
        "adds	x23, x23, x25\n\t"
        "umulh	x26, x17, x9\n\t"
        "adcs	x24, x24, x26\n\t"
        /* A[3] * B[1] */
        "mul	x25, x20, x9\n\t"
        "adcs	x4, x4, x25\n\t"
        "umulh	x26, x20, x9\n\t"
        "adcs	x5, x5, x26\n\t"
        "adc	x6, x6, xzr\n\t"
        /* A[2] * B[2] */
        "mul	x25, x19, x10\n\t"
        "adds	x4, x4, x25\n\t"
        "umulh	x26, x19, x10\n\t"
        "adcs	x5, x5, x26\n\t"
        /* A[3] * B[3] */
        "mul	x25, x20, x11\n\t"
        "adcs	x6, x6, x25\n\t"
        "umulh	x7, x20, x11\n\t"
        "adc	x7, x7, xzr\n\t"
        /* A[0] * B[3] */
        "mul	x25, x16, x11\n\t"
        "adds	x24, x24, x25\n\t"
        "umulh	x26, x16, x11\n\t"
        "adcs	x4, x4, x26\n\t"
        /* A[2] * B[3] */
        "mul	x25, x19, x11\n\t"
        "adcs	x5, x5, x25\n\t"
        "umulh	x26, x19, x11\n\t"
        "adcs	x6, x6, x26\n\t"
        "adc	x7, x7, xzr\n\t"
        /* A[3] * B[0] */
        "mul	x25, x20, x8\n\t"
        "adds	x24, x24, x25\n\t"
        "umulh	x26, x20, x8\n\t"
        "adcs	x4, x4, x26\n\t"
        /* A[3] * B[2] */
        "mul	x25, x20, x10\n\t"
        "adcs	x5, x5, x25\n\t"
        "umulh	x26, x20, x10\n\t"
        "adcs	x6, x6, x26\n\t"
        "adc	x7, x7, xzr\n\t"
        /* Reduce */
        "mov	x25, #38\n\t"
        "mul	x26, x25, x7\n\t"
        "adds	x24, x24, x26\n\t"
        "umulh	x27, x25, x7\n\t"
        "adc	x27, x27, xzr\n\t"
        "mov	x25, #19\n\t"
        "extr	x27, x27, x24, #63\n\t"
        "mul	x27, x27, x25\n\t"
        "and	x24, x24, #0x7fffffffffffffff\n\t"
        "mov	x25, #38\n\t"
        "mul	x26, x25, x4\n\t"
        "adds	x21, x21, x26\n\t"
        "umulh	x4, x25, x4\n\t"
        "mul	x26, x25, x5\n\t"
        "adcs	x22, x22, x26\n\t"
        "umulh	x5, x25, x5\n\t"
        "mul	x26, x25, x6\n\t"
        "adcs	x23, x23, x26\n\t"
        "umulh	x6, x25, x6\n\t"
        "adc	x24, x24, xzr\n\t"
        /*  Add high product results in */
        "adds	x21, x21, x27\n\t"
        "adcs	x22, x22, x4\n\t"
        "adcs	x23, x23, x5\n\t"
        "adc	x24, x24, x6\n\t"
        /* Reduce if top bit set */
        "mov	x25, #19\n\t"
        "and	x26, x25, x24, asr 63\n\t"
        "adds	x21, x21, x26\n\t"
        "adcs	x22, x22, xzr\n\t"
        "and	x24, x24, #0x7fffffffffffffff\n\t"
        "adcs	x23, x23, xzr\n\t"
        "adc	x24, x24, xzr\n\t"
        /* Store */
        "stp	x21, x22, [x0]\n\t"
        "stp	x23, x24, [x0, #16]\n\t"
        "sub	x2, x2, #32\n\t"
        "add	x1, x0, #32\n\t"
        "add	x0, x0, #32\n\t"
        /* Multiply */
        "ldp	x16, x17, [x2]\n\t"
        "ldp	x19, x20, [x2, #16]\n\t"
        /* A[0] * B[0] */
        "umulh	x5, x12, x16\n\t"
        "mul	x4, x12, x16\n\t"
        /* A[2] * B[0] */
        "umulh	x7, x14, x16\n\t"
        "mul	x6, x14, x16\n\t"
        /* A[1] * B[0] */
        "mul	x25, x13, x16\n\t"
        "adds	x5, x5, x25\n\t"
        "umulh	x26, x13, x16\n\t"
        "adcs	x6, x6, x26\n\t"
        /* A[1] * B[3] */
        "umulh	x9, x13, x20\n\t"
        "adc	x7, x7, xzr\n\t"
        "mul	x8, x13, x20\n\t"
        /* A[0] * B[1] */
        "mul	x25, x12, x17\n\t"
        "adds	x5, x5, x25\n\t"
        "umulh	x26, x12, x17\n\t"
        "adcs	x6, x6, x26\n\t"
        /* A[2] * B[1] */
        "mul	x25, x14, x17\n\t"
        "adcs	x7, x7, x25\n\t"
        "umulh	x26, x14, x17\n\t"
        "adcs	x8, x8, x26\n\t"
        "adc	x9, x9, xzr\n\t"
        /* A[1] * B[2] */
        "mul	x25, x13, x19\n\t"
        "adds	x7, x7, x25\n\t"
        "umulh	x26, x13, x19\n\t"
        "adcs	x8, x8, x26\n\t"
        "adcs	x9, x9, xzr\n\t"
        "adc	x10, xzr, xzr\n\t"
        /* A[0] * B[2] */
        "mul	x25, x12, x19\n\t"
        "adds	x6, x6, x25\n\t"
        "umulh	x26, x12, x19\n\t"
        "adcs	x7, x7, x26\n\t"
        "adcs	x8, x8, xzr\n\t"
        "adcs	x9, x9, xzr\n\t"
        "adc	x10, x10, xzr\n\t"
        /* A[1] * B[1] */
        "mul	x25, x13, x17\n\t"
        "adds	x6, x6, x25\n\t"
        "umulh	x26, x13, x17\n\t"
        "adcs	x7, x7, x26\n\t"
        /* A[3] * B[1] */
        "mul	x25, x15, x17\n\t"
        "adcs	x8, x8, x25\n\t"
        "umulh	x26, x15, x17\n\t"
        "adcs	x9, x9, x26\n\t"
        "adc	x10, x10, xzr\n\t"
        /* A[2] * B[2] */
        "mul	x25, x14, x19\n\t"
        "adds	x8, x8, x25\n\t"
        "umulh	x26, x14, x19\n\t"
        "adcs	x9, x9, x26\n\t"
        /* A[3] * B[3] */
        "mul	x25, x15, x20\n\t"
        "adcs	x10, x10, x25\n\t"
        "umulh	x11, x15, x20\n\t"
        "adc	x11, x11, xzr\n\t"
        /* A[0] * B[3] */
        "mul	x25, x12, x20\n\t"
        "adds	x7, x7, x25\n\t"
        "umulh	x26, x12, x20\n\t"
        "adcs	x8, x8, x26\n\t"
        /* A[2] * B[3] */
        "mul	x25, x14, x20\n\t"
        "adcs	x9, x9, x25\n\t"
        "umulh	x26, x14, x20\n\t"
        "adcs	x10, x10, x26\n\t"
        "adc	x11, x11, xzr\n\t"
        /* A[3] * B[0] */
        "mul	x25, x15, x16\n\t"
        "adds	x7, x7, x25\n\t"
        "umulh	x26, x15, x16\n\t"
        "adcs	x8, x8, x26\n\t"
        /* A[3] * B[2] */
        "mul	x25, x15, x19\n\t"
        "adcs	x9, x9, x25\n\t"
        "umulh	x26, x15, x19\n\t"
        "adcs	x10, x10, x26\n\t"
        "adc	x11, x11, xzr\n\t"
        /* Reduce */
        "mov	x25, #38\n\t"
        "mul	x26, x25, x11\n\t"
        "adds	x7, x7, x26\n\t"
        "umulh	x27, x25, x11\n\t"
        "adc	x27, x27, xzr\n\t"
        "mov	x25, #19\n\t"
        "extr	x27, x27, x7, #63\n\t"
        "mul	x27, x27, x25\n\t"
        "and	x7, x7, #0x7fffffffffffffff\n\t"
        "mov	x25, #38\n\t"
        "mul	x26, x25, x8\n\t"
        "adds	x4, x4, x26\n\t"
        "umulh	x8, x25, x8\n\t"
        "mul	x26, x25, x9\n\t"
        "adcs	x5, x5, x26\n\t"
        "umulh	x9, x25, x9\n\t"
        "mul	x26, x25, x10\n\t"
        "adcs	x6, x6, x26\n\t"
        "umulh	x10, x25, x10\n\t"
        "adc	x7, x7, xzr\n\t"
        /*  Add high product results in */
        "adds	x4, x4, x27\n\t"
        "adcs	x5, x5, x8\n\t"
        "adcs	x6, x6, x9\n\t"
        "adc	x7, x7, x10\n\t"
        /* Store */
        "stp	x4, x5, [x0]\n\t"
        "stp	x6, x7, [x0, #16]\n\t"
        "mov	x3, x0\n\t"
        "sub	x2, x0, #32\n\t"
        "sub	x1, x0, #32\n\t"
        /* Add */
        "adds	x8, x21, x4\n\t"
        "adcs	x9, x22, x5\n\t"
        "adcs	x10, x23, x6\n\t"
        "adcs	x11, x24, x7\n\t"
        "cset	x28, cs\n\t"
        "mov	x25, #19\n\t"
        "extr	x28, x28, x11, #63\n\t"
        "mul	x25, x28, x25\n\t"
        /*   Sub modulus (if overflow) */
        "adds	x8, x8, x25\n\t"
        "adcs	x9, x9, xzr\n\t"
        "and	x11, x11, #0x7fffffffffffffff\n\t"
        "adcs	x10, x10, xzr\n\t"
        "adc	x11, x11, xzr\n\t"
        /* Sub */
        "subs	x12, x21, x4\n\t"
        "sbcs	x13, x22, x5\n\t"
        "sbcs	x14, x23, x6\n\t"
        "sbcs	x15, x24, x7\n\t"
        "csetm	x28, cc\n\t"
        "mov	x25, #-19\n\t"
        "extr	x28, x28, x15, #63\n\t"
        "mul	x25, x28, x25\n\t"
        /*   Add modulus (if underflow) */
        "subs	x12, x12, x25\n\t"
        "sbcs	x13, x13, xzr\n\t"
        "and	x15, x15, #0x7fffffffffffffff\n\t"
        "sbcs	x14, x14, xzr\n\t"
        "sbc	x15, x15, xzr\n\t"
        "stp	x8, x9, [x0]\n\t"
        "stp	x10, x11, [x0, #16]\n\t"
        "stp	x12, x13, [x1]\n\t"
        "stp	x14, x15, [x1, #16]\n\t"
        "ldr	x1, [x29, #24]\n\t"
        "ldr	x2, [x29, #32]\n\t"
        "add	x2, x2, #0x60\n\t"
        "add	x1, x1, #0x60\n\t"
        "add	x0, x0, #0x40\n\t"
        /* Multiply */
        "ldp	x21, x22, [x1]\n\t"
        "ldp	x23, x24, [x1, #16]\n\t"
        "ldp	x4, x5, [x2]\n\t"
        "ldp	x6, x7, [x2, #16]\n\t"
        /* A[0] * B[0] */
        "umulh	x17, x21, x4\n\t"
        "mul	x16, x21, x4\n\t"
        /* A[2] * B[0] */
        "umulh	x20, x23, x4\n\t"
        "mul	x19, x23, x4\n\t"
        /* A[1] * B[0] */
        "mul	x25, x22, x4\n\t"
        "adds	x17, x17, x25\n\t"
        "umulh	x26, x22, x4\n\t"
        "adcs	x19, x19, x26\n\t"
        /* A[1] * B[3] */
        "umulh	x9, x22, x7\n\t"
        "adc	x20, x20, xzr\n\t"
        "mul	x8, x22, x7\n\t"
        /* A[0] * B[1] */
        "mul	x25, x21, x5\n\t"
        "adds	x17, x17, x25\n\t"
        "umulh	x26, x21, x5\n\t"
        "adcs	x19, x19, x26\n\t"
        /* A[2] * B[1] */
        "mul	x25, x23, x5\n\t"
        "adcs	x20, x20, x25\n\t"
        "umulh	x26, x23, x5\n\t"
        "adcs	x8, x8, x26\n\t"
        "adc	x9, x9, xzr\n\t"
        /* A[1] * B[2] */
        "mul	x25, x22, x6\n\t"
        "adds	x20, x20, x25\n\t"
        "umulh	x26, x22, x6\n\t"
        "adcs	x8, x8, x26\n\t"
        "adcs	x9, x9, xzr\n\t"
        "adc	x10, xzr, xzr\n\t"
        /* A[0] * B[2] */
        "mul	x25, x21, x6\n\t"
        "adds	x19, x19, x25\n\t"
        "umulh	x26, x21, x6\n\t"
        "adcs	x20, x20, x26\n\t"
        "adcs	x8, x8, xzr\n\t"
        "adcs	x9, x9, xzr\n\t"
        "adc	x10, x10, xzr\n\t"
        /* A[1] * B[1] */
        "mul	x25, x22, x5\n\t"
        "adds	x19, x19, x25\n\t"
        "umulh	x26, x22, x5\n\t"
        "adcs	x20, x20, x26\n\t"
        /* A[3] * B[1] */
        "mul	x25, x24, x5\n\t"
        "adcs	x8, x8, x25\n\t"
        "umulh	x26, x24, x5\n\t"
        "adcs	x9, x9, x26\n\t"
        "adc	x10, x10, xzr\n\t"
        /* A[2] * B[2] */
        "mul	x25, x23, x6\n\t"
        "adds	x8, x8, x25\n\t"
        "umulh	x26, x23, x6\n\t"
        "adcs	x9, x9, x26\n\t"
        /* A[3] * B[3] */
        "mul	x25, x24, x7\n\t"
        "adcs	x10, x10, x25\n\t"
        "umulh	x11, x24, x7\n\t"
        "adc	x11, x11, xzr\n\t"
        /* A[0] * B[3] */
        "mul	x25, x21, x7\n\t"
        "adds	x20, x20, x25\n\t"
        "umulh	x26, x21, x7\n\t"
        "adcs	x8, x8, x26\n\t"
        /* A[2] * B[3] */
        "mul	x25, x23, x7\n\t"
        "adcs	x9, x9, x25\n\t"
        "umulh	x26, x23, x7\n\t"
        "adcs	x10, x10, x26\n\t"
        "adc	x11, x11, xzr\n\t"
        /* A[3] * B[0] */
        "mul	x25, x24, x4\n\t"
        "adds	x20, x20, x25\n\t"
        "umulh	x26, x24, x4\n\t"
        "adcs	x8, x8, x26\n\t"
        /* A[3] * B[2] */
        "mul	x25, x24, x6\n\t"
        "adcs	x9, x9, x25\n\t"
        "umulh	x26, x24, x6\n\t"
        "adcs	x10, x10, x26\n\t"
        "adc	x11, x11, xzr\n\t"
        /* Reduce */
        "mov	x25, #38\n\t"
        "mul	x26, x25, x11\n\t"
        "adds	x20, x20, x26\n\t"
        "umulh	x27, x25, x11\n\t"
        "adc	x27, x27, xzr\n\t"
        "mov	x25, #19\n\t"
        "extr	x27, x27, x20, #63\n\t"
        "mul	x27, x27, x25\n\t"
        "and	x20, x20, #0x7fffffffffffffff\n\t"
        "mov	x25, #38\n\t"
        "mul	x26, x25, x8\n\t"
        "adds	x16, x16, x26\n\t"
        "umulh	x8, x25, x8\n\t"
        "mul	x26, x25, x9\n\t"
        "adcs	x17, x17, x26\n\t"
        "umulh	x9, x25, x9\n\t"
        "mul	x26, x25, x10\n\t"
        "adcs	x19, x19, x26\n\t"
        "umulh	x10, x25, x10\n\t"
        "adc	x20, x20, xzr\n\t"
        /*  Add high product results in */
        "adds	x16, x16, x27\n\t"
        "adcs	x17, x17, x8\n\t"
        "adcs	x19, x19, x9\n\t"
        "adc	x20, x20, x10\n\t"
        /* Reduce if top bit set */
        "mov	x25, #19\n\t"
        "and	x26, x25, x20, asr 63\n\t"
        "adds	x16, x16, x26\n\t"
        "adcs	x17, x17, xzr\n\t"
        "and	x20, x20, #0x7fffffffffffffff\n\t"
        "adcs	x19, x19, xzr\n\t"
        "adc	x20, x20, xzr\n\t"
        /* Store */
        "stp	x16, x17, [x0]\n\t"
        "stp	x19, x20, [x0, #16]\n\t"
        "sub	x3, x2, #32\n\t"
        "sub	x2, x1, #32\n\t"
        "sub	x1, x0, #32\n\t"
        /* Multiply */
        "ldp	x4, x5, [x2]\n\t"
        "ldp	x6, x7, [x2, #16]\n\t"
        "ldp	x12, x13, [x3]\n\t"
        "ldp	x14, x15, [x3, #16]\n\t"
        /* A[0] * B[0] */
        "umulh	x9, x4, x12\n\t"
        "mul	x8, x4, x12\n\t"
        /* A[2] * B[0] */
        "umulh	x11, x6, x12\n\t"
        "mul	x10, x6, x12\n\t"
        /* A[1] * B[0] */
        "mul	x25, x5, x12\n\t"
        "adds	x9, x9, x25\n\t"
        "umulh	x26, x5, x12\n\t"
        "adcs	x10, x10, x26\n\t"
        /* A[1] * B[3] */
        "umulh	x17, x5, x15\n\t"
        "adc	x11, x11, xzr\n\t"
        "mul	x16, x5, x15\n\t"
        /* A[0] * B[1] */
        "mul	x25, x4, x13\n\t"
        "adds	x9, x9, x25\n\t"
        "umulh	x26, x4, x13\n\t"
        "adcs	x10, x10, x26\n\t"
        /* A[2] * B[1] */
        "mul	x25, x6, x13\n\t"
        "adcs	x11, x11, x25\n\t"
        "umulh	x26, x6, x13\n\t"
        "adcs	x16, x16, x26\n\t"
        "adc	x17, x17, xzr\n\t"
        /* A[1] * B[2] */
        "mul	x25, x5, x14\n\t"
        "adds	x11, x11, x25\n\t"
        "umulh	x26, x5, x14\n\t"
        "adcs	x16, x16, x26\n\t"
        "adcs	x17, x17, xzr\n\t"
        "adc	x19, xzr, xzr\n\t"
        /* A[0] * B[2] */
        "mul	x25, x4, x14\n\t"
        "adds	x10, x10, x25\n\t"
        "umulh	x26, x4, x14\n\t"
        "adcs	x11, x11, x26\n\t"
        "adcs	x16, x16, xzr\n\t"
        "adcs	x17, x17, xzr\n\t"
        "adc	x19, x19, xzr\n\t"
        /* A[1] * B[1] */
        "mul	x25, x5, x13\n\t"
        "adds	x10, x10, x25\n\t"
        "umulh	x26, x5, x13\n\t"
        "adcs	x11, x11, x26\n\t"
        /* A[3] * B[1] */
        "mul	x25, x7, x13\n\t"
        "adcs	x16, x16, x25\n\t"
        "umulh	x26, x7, x13\n\t"
        "adcs	x17, x17, x26\n\t"
        "adc	x19, x19, xzr\n\t"
        /* A[2] * B[2] */
        "mul	x25, x6, x14\n\t"
        "adds	x16, x16, x25\n\t"
        "umulh	x26, x6, x14\n\t"
        "adcs	x17, x17, x26\n\t"
        /* A[3] * B[3] */
        "mul	x25, x7, x15\n\t"
        "adcs	x19, x19, x25\n\t"
        "umulh	x20, x7, x15\n\t"
        "adc	x20, x20, xzr\n\t"
        /* A[0] * B[3] */
        "mul	x25, x4, x15\n\t"
        "adds	x11, x11, x25\n\t"
        "umulh	x26, x4, x15\n\t"
        "adcs	x16, x16, x26\n\t"
        /* A[2] * B[3] */
        "mul	x25, x6, x15\n\t"
        "adcs	x17, x17, x25\n\t"
        "umulh	x26, x6, x15\n\t"
        "adcs	x19, x19, x26\n\t"
        "adc	x20, x20, xzr\n\t"
        /* A[3] * B[0] */
        "mul	x25, x7, x12\n\t"
        "adds	x11, x11, x25\n\t"
        "umulh	x26, x7, x12\n\t"
        "adcs	x16, x16, x26\n\t"
        /* A[3] * B[2] */
        "mul	x25, x7, x14\n\t"
        "adcs	x17, x17, x25\n\t"
        "umulh	x26, x7, x14\n\t"
        "adcs	x19, x19, x26\n\t"
        "adc	x20, x20, xzr\n\t"
        /* Reduce */
        "mov	x25, #38\n\t"
        "mul	x26, x25, x20\n\t"
        "adds	x11, x11, x26\n\t"
        "umulh	x27, x25, x20\n\t"
        "adc	x27, x27, xzr\n\t"
        "mov	x25, #19\n\t"
        "extr	x27, x27, x11, #63\n\t"
        "mul	x27, x27, x25\n\t"
        "and	x11, x11, #0x7fffffffffffffff\n\t"
        "mov	x25, #38\n\t"
        "mul	x26, x25, x16\n\t"
        "adds	x8, x8, x26\n\t"
        "umulh	x16, x25, x16\n\t"
        "mul	x26, x25, x17\n\t"
        "adcs	x9, x9, x26\n\t"
        "umulh	x17, x25, x17\n\t"
        "mul	x26, x25, x19\n\t"
        "adcs	x10, x10, x26\n\t"
        "umulh	x19, x25, x19\n\t"
        "adc	x11, x11, xzr\n\t"
        /*  Add high product results in */
        "adds	x8, x8, x27\n\t"
        "adcs	x9, x9, x16\n\t"
        "adcs	x10, x10, x17\n\t"
        "adc	x11, x11, x19\n\t"
        /* Double */
        "adds	x8, x8, x8\n\t"
        "adcs	x9, x9, x9\n\t"
        "adcs	x10, x10, x10\n\t"
        "adc	x11, x11, x11\n\t"
        "mov	x25, #-19\n\t"
        "asr	x28, x11, #63\n\t"
        /*   Mask the modulus */
        "and	x25, x28, x25\n\t"
        "and	x26, x28, #0x7fffffffffffffff\n\t"
        /*   Sub modulus (if overflow) */
        "subs	x8, x8, x25\n\t"
        "sbcs	x9, x9, x28\n\t"
        "sbcs	x10, x10, x28\n\t"
        "sbc	x11, x11, x26\n\t"
        "mov	x3, x0\n\t"
        "sub	x2, x0, #32\n\t"
        /* Add */
        "ldp	x4, x5, [x3]\n\t"
        "ldp	x6, x7, [x3, #16]\n\t"
        "adds	x12, x8, x4\n\t"
        "adcs	x13, x9, x5\n\t"
        "adcs	x14, x10, x6\n\t"
        "adcs	x15, x11, x7\n\t"
        "cset	x28, cs\n\t"
        "mov	x25, #19\n\t"
        "extr	x28, x28, x15, #63\n\t"
        "mul	x25, x28, x25\n\t"
        /*   Sub modulus (if overflow) */
        "adds	x12, x12, x25\n\t"
        "adcs	x13, x13, xzr\n\t"
        "and	x15, x15, #0x7fffffffffffffff\n\t"
        "adcs	x14, x14, xzr\n\t"
        "adc	x15, x15, xzr\n\t"
        /* Sub */
        "subs	x21, x8, x4\n\t"
        "sbcs	x22, x9, x5\n\t"
        "sbcs	x23, x10, x6\n\t"
        "sbcs	x24, x11, x7\n\t"
        "csetm	x28, cc\n\t"
        "mov	x25, #-19\n\t"
        "extr	x28, x28, x24, #63\n\t"
        "mul	x25, x28, x25\n\t"
        /*   Add modulus (if underflow) */
        "subs	x21, x21, x25\n\t"
        "sbcs	x22, x22, xzr\n\t"
        "and	x24, x24, #0x7fffffffffffffff\n\t"
        "sbcs	x23, x23, xzr\n\t"
        "sbc	x24, x24, xzr\n\t"
        "stp	x12, x13, [x0]\n\t"
        "stp	x14, x15, [x0, #16]\n\t"
        "stp	x21, x22, [x1]\n\t"
        "stp	x23, x24, [x1, #16]\n\t"
        "ldp	x29, x30, [sp], #48\n\t"
        : [r] "+r" (r)
        : [p] "r" (p), [q] "r" (q)
        : "memory", "cc", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10",
            "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20",
            "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28"
    );
}

void sc_reduce(byte* s)
{
    __asm__ __volatile__ (
        "ldp	x2, x3, [%x[s]]\n\t"
        "ldp	x4, x5, [%x[s], #16]\n\t"
        "ldp	x6, x7, [%x[s], #32]\n\t"
        "ldp	x8, x9, [%x[s], #48]\n\t"
        "lsr	x23, x9, #56\n\t"
        "lsl	x9, x9, #4\n\t"
        "orr	x9, x9, x8, lsr 60\n\t"
        "lsl	x8, x8, #4\n\t"
        "orr	x8, x8, x7, lsr 60\n\t"
        "lsl	x7, x7, #4\n\t"
        "orr	x7, x7, x6, lsr 60\n\t"
        "lsl	x6, x6, #4\n\t"
        "mov	x1, #15\n\t"
        "orr	x6, x6, x5, lsr 60\n\t"
        "bic	x5, x5, x1, lsl 60\n\t"
        "bic	x9, x9, x1, lsl 60\n\t"
        /* Add order times bits 504..511 */
        "mov	x11, #0x2c13\n\t"
        "movk	x11, #0xa30a, lsl 16\n\t"
        "movk	x11, #0x9ce5, lsl 32\n\t"
        "movk	x11, #0xa7ed, lsl 48\n\t"
        "mov	x13, #0x6329\n\t"
        "movk	x13, #0x5d08, lsl 16\n\t"
        "movk	x13, #0x621, lsl 32\n\t"
        "movk	x13, #0xeb21, lsl 48\n\t"
        "mul	x10, x23, x11\n\t"
        "umulh	x11, x23, x11\n\t"
        "mul	x12, x23, x13\n\t"
        "umulh	x13, x23, x13\n\t"
        "adds	x6, x6, x10\n\t"
        "adcs	x7, x7, x11\n\t"
        "adcs	x8, x8, xzr\n\t"
        "adc	x9, x9, xzr\n\t"
        "adds	x7, x7, x12\n\t"
        "adcs	x8, x8, x13\n\t"
        "adc	x9, x9, xzr\n\t"
        "subs	x8, x8, x23\n\t"
        "sbc	x9, x9, xzr\n\t"
        /* Sub product of top 4 words and order */
        "mov	x1, #0x2c13\n\t"
        "movk	x1, #0xa30a, lsl 16\n\t"
        "movk	x1, #0x9ce5, lsl 32\n\t"
        "movk	x1, #0xa7ed, lsl 48\n\t"
        "mul	x10, x6, x1\n\t"
        "umulh	x11, x6, x1\n\t"
        "mul	x12, x7, x1\n\t"
        "umulh	x13, x7, x1\n\t"
        "mul	x14, x8, x1\n\t"
        "umulh	x15, x8, x1\n\t"
        "mul	x16, x9, x1\n\t"
        "umulh	x17, x9, x1\n\t"
        "adds	x2, x2, x10\n\t"
        "adcs	x3, x3, x11\n\t"
        "adcs	x4, x4, x14\n\t"
        "adcs	x5, x5, x15\n\t"
        "adc	x19, xzr, xzr\n\t"
        "adds	x3, x3, x12\n\t"
        "adcs	x4, x4, x13\n\t"
        "adcs	x5, x5, x16\n\t"
        "adc	x19, x19, x17\n\t"
        "mov	x1, #0x6329\n\t"
        "movk	x1, #0x5d08, lsl 16\n\t"
        "movk	x1, #0x621, lsl 32\n\t"
        "movk	x1, #0xeb21, lsl 48\n\t"
        "mul	x10, x6, x1\n\t"
        "umulh	x11, x6, x1\n\t"
        "mul	x12, x7, x1\n\t"
        "umulh	x13, x7, x1\n\t"
        "mul	x14, x8, x1\n\t"
        "umulh	x15, x8, x1\n\t"
        "mul	x16, x9, x1\n\t"
        "umulh	x17, x9, x1\n\t"
        "adds	x3, x3, x10\n\t"
        "adcs	x4, x4, x11\n\t"
        "adcs	x5, x5, x14\n\t"
        "adcs	x19, x19, x15\n\t"
        "adc	x20, xzr, xzr\n\t"
        "adds	x4, x4, x12\n\t"
        "adcs	x5, x5, x13\n\t"
        "adcs	x19, x19, x16\n\t"
        "adc	x20, x20, x17\n\t"
        "subs	x4, x4, x6\n\t"
        "sbcs	x5, x5, x7\n\t"
        "sbcs	x6, x19, x8\n\t"
        "sbc	x7, x20, x9\n\t"
        "asr	x23, x7, #57\n\t"
        /*   Conditionally subtract order starting at bit 125 */
        "mov	x10, xzr\n\t"
        "mov	x13, xzr\n\t"
        "mov	x11, #0xba7d\n\t"
        "movk	x11, #0x4b9e, lsl 16\n\t"
        "movk	x11, #0x4c63, lsl 32\n\t"
        "movk	x11, #0xcb02, lsl 48\n\t"
        "mov	x12, #0xf39a\n\t"
        "movk	x12, #0xd45e, lsl 16\n\t"
        "movk	x12, #0xdf3b, lsl 32\n\t"
        "movk	x12, #0x29b, lsl 48\n\t"
        "movk	x10, #0xa000, lsl 48\n\t"
        "movk	x13, #0x200, lsl 48\n\t"
        "and	x10, x10, x23\n\t"
        "and	x11, x11, x23\n\t"
        "and	x12, x12, x23\n\t"
        "and	x13, x13, x23\n\t"
        "adds	x3, x3, x10\n\t"
        "adcs	x4, x4, x11\n\t"
        "adcs	x5, x5, x12\n\t"
        "adcs	x6, x6, xzr\n\t"
        "adc	x7, x7, x13\n\t"
        /*   Move bits 252-376 to own registers */
        "lsl	x7, x7, #4\n\t"
        "orr	x7, x7, x6, lsr 60\n\t"
        "lsl	x6, x6, #4\n\t"
        "mov	x23, #15\n\t"
        "orr	x6, x6, x5, lsr 60\n\t"
        "bic	x5, x5, x23, lsl 60\n\t"
        /* Sub product of top 2 words and order */
        /*   * -5812631a5cf5d3ed */
        "mov	x1, #0x2c13\n\t"
        "movk	x1, #0xa30a, lsl 16\n\t"
        "movk	x1, #0x9ce5, lsl 32\n\t"
        "movk	x1, #0xa7ed, lsl 48\n\t"
        "mul	x10, x6, x1\n\t"
        "umulh	x11, x6, x1\n\t"
        "mul	x12, x7, x1\n\t"
        "umulh	x13, x7, x1\n\t"
        "adds	x2, x2, x10\n\t"
        "adcs	x3, x3, x11\n\t"
        "adc	x19, xzr, xzr\n\t"
        "adds	x3, x3, x12\n\t"
        "adc	x19, x19, x13\n\t"
        /*   * -14def9dea2f79cd7 */
        "mov	x1, #0x6329\n\t"
        "movk	x1, #0x5d08, lsl 16\n\t"
        "movk	x1, #0x621, lsl 32\n\t"
        "movk	x1, #0xeb21, lsl 48\n\t"
        "mul	x10, x6, x1\n\t"
        "umulh	x11, x6, x1\n\t"
        "mul	x12, x7, x1\n\t"
        "umulh	x13, x7, x1\n\t"
        "adds	x3, x3, x10\n\t"
        "adcs	x4, x4, x11\n\t"
        "adc	x20, xzr, xzr\n\t"
        "adds	x4, x4, x12\n\t"
        "adc	x20, x20, x13\n\t"
        /*   Add overflows at 2 * 64 */
        "mov	x1, #15\n\t"
        "bic	x5, x5, x1, lsl 60\n\t"
        "adds	x4, x4, x19\n\t"
        "adc	x5, x5, x20\n\t"
        /*   Subtract top at 2 * 64 */
        "subs	x4, x4, x6\n\t"
        "sbcs	x5, x5, x7\n\t"
        "sbc	x1, x1, x1\n\t"
        /*   Conditional sub order */
        "mov	x10, #0xd3ed\n\t"
        "movk	x10, #0x5cf5, lsl 16\n\t"
        "movk	x10, #0x631a, lsl 32\n\t"
        "movk	x10, #0x5812, lsl 48\n\t"
        "mov	x11, #0x9cd6\n\t"
        "movk	x11, #0xa2f7, lsl 16\n\t"
        "movk	x11, #0xf9de, lsl 32\n\t"
        "movk	x11, #0x14de, lsl 48\n\t"
        "and	x10, x10, x1\n\t"
        "and	x11, x11, x1\n\t"
        "adds	x2, x2, x10\n\t"
        "adcs	x3, x3, x11\n\t"
        "and	x1, x1, #0x1000000000000000\n\t"
        "adcs	x4, x4, xzr\n\t"
        "mov	x23, #15\n\t"
        "adc	x5, x5, x1\n\t"
        "bic	x5, x5, x23, lsl 60\n\t"
        /* Store result */
        "stp	x2, x3, [%x[s]]\n\t"
        "stp	x4, x5, [%x[s], #16]\n\t"
        : [s] "+r" (s)
        :
        : "memory", "cc", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9",
            "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19",
            "x20", "x21", "x22", "x23"
    );
}

void sc_muladd(byte* s, const byte* a, const byte* b, const byte* c)
{
    __asm__ __volatile__ (
        /* Multiply */
        "ldp	x12, x13, [%x[a]]\n\t"
        "ldp	x14, x15, [%x[a], #16]\n\t"
        "ldp	x16, x17, [%x[b]]\n\t"
        "ldp	x19, x20, [%x[b], #16]\n\t"
        /* A[0] * B[0] */
        "umulh	x5, x12, x16\n\t"
        "mul	x4, x12, x16\n\t"
        /* A[2] * B[0] */
        "umulh	x7, x14, x16\n\t"
        "mul	x6, x14, x16\n\t"
        /* A[1] * B[0] */
        "mul	x21, x13, x16\n\t"
        "adds	x5, x5, x21\n\t"
        "umulh	x22, x13, x16\n\t"
        "adcs	x6, x6, x22\n\t"
        /* A[1] * B[3] */
        "umulh	x9, x13, x20\n\t"
        "adc	x7, x7, xzr\n\t"
        "mul	x8, x13, x20\n\t"
        /* A[0] * B[1] */
        "mul	x21, x12, x17\n\t"
        "adds	x5, x5, x21\n\t"
        "umulh	x22, x12, x17\n\t"
        "adcs	x6, x6, x22\n\t"
        /* A[2] * B[1] */
        "mul	x21, x14, x17\n\t"
        "adcs	x7, x7, x21\n\t"
        "umulh	x22, x14, x17\n\t"
        "adcs	x8, x8, x22\n\t"
        "adc	x9, x9, xzr\n\t"
        /* A[1] * B[2] */
        "mul	x21, x13, x19\n\t"
        "adds	x7, x7, x21\n\t"
        "umulh	x22, x13, x19\n\t"
        "adcs	x8, x8, x22\n\t"
        "adcs	x9, x9, xzr\n\t"
        "adc	x10, xzr, xzr\n\t"
        /* A[0] * B[2] */
        "mul	x21, x12, x19\n\t"
        "adds	x6, x6, x21\n\t"
        "umulh	x22, x12, x19\n\t"
        "adcs	x7, x7, x22\n\t"
        "adcs	x8, x8, xzr\n\t"
        "adcs	x9, x9, xzr\n\t"
        "adc	x10, x10, xzr\n\t"
        /* A[1] * B[1] */
        "mul	x21, x13, x17\n\t"
        "adds	x6, x6, x21\n\t"
        "umulh	x22, x13, x17\n\t"
        "adcs	x7, x7, x22\n\t"
        /* A[3] * B[1] */
        "mul	x21, x15, x17\n\t"
        "adcs	x8, x8, x21\n\t"
        "umulh	x22, x15, x17\n\t"
        "adcs	x9, x9, x22\n\t"
        "adc	x10, x10, xzr\n\t"
        /* A[2] * B[2] */
        "mul	x21, x14, x19\n\t"
        "adds	x8, x8, x21\n\t"
        "umulh	x22, x14, x19\n\t"
        "adcs	x9, x9, x22\n\t"
        /* A[3] * B[3] */
        "mul	x21, x15, x20\n\t"
        "adcs	x10, x10, x21\n\t"
        "umulh	x11, x15, x20\n\t"
        "adc	x11, x11, xzr\n\t"
        /* A[0] * B[3] */
        "mul	x21, x12, x20\n\t"
        "adds	x7, x7, x21\n\t"
        "umulh	x22, x12, x20\n\t"
        "adcs	x8, x8, x22\n\t"
        /* A[2] * B[3] */
        "mul	x21, x14, x20\n\t"
        "adcs	x9, x9, x21\n\t"
        "umulh	x22, x14, x20\n\t"
        "adcs	x10, x10, x22\n\t"
        "adc	x11, x11, xzr\n\t"
        /* A[3] * B[0] */
        "mul	x21, x15, x16\n\t"
        "adds	x7, x7, x21\n\t"
        "umulh	x22, x15, x16\n\t"
        "adcs	x8, x8, x22\n\t"
        /* A[3] * B[2] */
        "mul	x21, x15, x19\n\t"
        "adcs	x9, x9, x21\n\t"
        "umulh	x22, x15, x19\n\t"
        "adcs	x10, x10, x22\n\t"
        "adc	x11, x11, xzr\n\t"
        /* Add c to a * b */
        "ldp	x12, x13, [%x[c]]\n\t"
        "ldp	x14, x15, [%x[c], #16]\n\t"
        "adds	x4, x4, x12\n\t"
        "adcs	x5, x5, x13\n\t"
        "adcs	x6, x6, x14\n\t"
        "adcs	x7, x7, x15\n\t"
        "adcs	x8, x8, xzr\n\t"
        "adcs	x9, x9, xzr\n\t"
        "adcs	x10, x10, xzr\n\t"
        "adc	x11, x11, xzr\n\t"
        "lsr	x25, x11, #56\n\t"
        "lsl	x11, x11, #4\n\t"
        "orr	x11, x11, x10, lsr 60\n\t"
        "lsl	x10, x10, #4\n\t"
        "orr	x10, x10, x9, lsr 60\n\t"
        "lsl	x9, x9, #4\n\t"
        "orr	x9, x9, x8, lsr 60\n\t"
        "lsl	x8, x8, #4\n\t"
        "mov	x26, #15\n\t"
        "orr	x8, x8, x7, lsr 60\n\t"
        "bic	x7, x7, x26, lsl 60\n\t"
        "bic	x11, x11, x26, lsl 60\n\t"
        /* Add order times bits 504..507 */
        "mov	x22, #0x2c13\n\t"
        "movk	x22, #0xa30a, lsl 16\n\t"
        "movk	x22, #0x9ce5, lsl 32\n\t"
        "movk	x22, #0xa7ed, lsl 48\n\t"
        "mov	x24, #0x6329\n\t"
        "movk	x24, #0x5d08, lsl 16\n\t"
        "movk	x24, #0x621, lsl 32\n\t"
        "movk	x24, #0xeb21, lsl 48\n\t"
        "mul	x21, x25, x22\n\t"
        "umulh	x22, x25, x22\n\t"
        "mul	x23, x25, x24\n\t"
        "umulh	x24, x25, x24\n\t"
        "adds	x8, x8, x21\n\t"
        "adcs	x9, x9, x22\n\t"
        "adcs	x10, x10, xzr\n\t"
        "adc	x11, x11, xzr\n\t"
        "adds	x9, x9, x23\n\t"
        "adcs	x10, x10, x24\n\t"
        "adc	x11, x11, xzr\n\t"
        "subs	x10, x10, x25\n\t"
        "sbc	x11, x11, xzr\n\t"
        /* Sub product of top 4 words and order */
        "mov	x26, #0x2c13\n\t"
        "movk	x26, #0xa30a, lsl 16\n\t"
        "movk	x26, #0x9ce5, lsl 32\n\t"
        "movk	x26, #0xa7ed, lsl 48\n\t"
        "mul	x16, x8, x26\n\t"
        "umulh	x17, x8, x26\n\t"
        "mul	x19, x9, x26\n\t"
        "umulh	x20, x9, x26\n\t"
        "mul	x21, x10, x26\n\t"
        "umulh	x22, x10, x26\n\t"
        "mul	x23, x11, x26\n\t"
        "umulh	x24, x11, x26\n\t"
        "adds	x4, x4, x16\n\t"
        "adcs	x5, x5, x17\n\t"
        "adcs	x6, x6, x21\n\t"
        "adcs	x7, x7, x22\n\t"
        "adc	x12, xzr, xzr\n\t"
        "adds	x5, x5, x19\n\t"
        "adcs	x6, x6, x20\n\t"
        "adcs	x7, x7, x23\n\t"
        "adc	x12, x12, x24\n\t"
        "mov	x26, #0x6329\n\t"
        "movk	x26, #0x5d08, lsl 16\n\t"
        "movk	x26, #0x621, lsl 32\n\t"
        "movk	x26, #0xeb21, lsl 48\n\t"
        "mul	x16, x8, x26\n\t"
        "umulh	x17, x8, x26\n\t"
        "mul	x19, x9, x26\n\t"
        "umulh	x20, x9, x26\n\t"
        "mul	x21, x10, x26\n\t"
        "umulh	x22, x10, x26\n\t"
        "mul	x23, x11, x26\n\t"
        "umulh	x24, x11, x26\n\t"
        "adds	x5, x5, x16\n\t"
        "adcs	x6, x6, x17\n\t"
        "adcs	x7, x7, x21\n\t"
        "adcs	x12, x12, x22\n\t"
        "adc	x13, xzr, xzr\n\t"
        "adds	x6, x6, x19\n\t"
        "adcs	x7, x7, x20\n\t"
        "adcs	x12, x12, x23\n\t"
        "adc	x13, x13, x24\n\t"
        "subs	x6, x6, x8\n\t"
        "sbcs	x7, x7, x9\n\t"
        "sbcs	x8, x12, x10\n\t"
        "sbc	x9, x13, x11\n\t"
        "asr	x25, x9, #57\n\t"
        /*   Conditionally subtract order starting at bit 125 */
        "mov	x16, xzr\n\t"
        "mov	x20, xzr\n\t"
        "mov	x17, #0xba7d\n\t"
        "movk	x17, #0x4b9e, lsl 16\n\t"
        "movk	x17, #0x4c63, lsl 32\n\t"
        "movk	x17, #0xcb02, lsl 48\n\t"
        "mov	x19, #0xf39a\n\t"
        "movk	x19, #0xd45e, lsl 16\n\t"
        "movk	x19, #0xdf3b, lsl 32\n\t"
        "movk	x19, #0x29b, lsl 48\n\t"
        "movk	x16, #0xa000, lsl 48\n\t"
        "movk	x20, #0x200, lsl 48\n\t"
        "and	x16, x16, x25\n\t"
        "and	x17, x17, x25\n\t"
        "and	x19, x19, x25\n\t"
        "and	x20, x20, x25\n\t"
        "adds	x5, x5, x16\n\t"
        "adcs	x6, x6, x17\n\t"
        "adcs	x7, x7, x19\n\t"
        "adcs	x8, x8, xzr\n\t"
        "adc	x9, x9, x20\n\t"
        /*   Move bits 252-376 to own registers */
        "lsl	x9, x9, #4\n\t"
        "orr	x9, x9, x8, lsr 60\n\t"
        "lsl	x8, x8, #4\n\t"
        "mov	x25, #15\n\t"
        "orr	x8, x8, x7, lsr 60\n\t"
        "bic	x7, x7, x25, lsl 60\n\t"
        /* Sub product of top 2 words and order */
        /*   * -5812631a5cf5d3ed */
        "mov	x26, #0x2c13\n\t"
        "movk	x26, #0xa30a, lsl 16\n\t"
        "movk	x26, #0x9ce5, lsl 32\n\t"
        "movk	x26, #0xa7ed, lsl 48\n\t"
        "mul	x16, x8, x26\n\t"
        "umulh	x17, x8, x26\n\t"
        "mul	x19, x9, x26\n\t"
        "umulh	x20, x9, x26\n\t"
        "adds	x4, x4, x16\n\t"
        "adcs	x5, x5, x17\n\t"
        "adc	x12, xzr, xzr\n\t"
        "adds	x5, x5, x19\n\t"
        "adc	x12, x12, x20\n\t"
        /*   * -14def9dea2f79cd7 */
        "mov	x26, #0x6329\n\t"
        "movk	x26, #0x5d08, lsl 16\n\t"
        "movk	x26, #0x621, lsl 32\n\t"
        "movk	x26, #0xeb21, lsl 48\n\t"
        "mul	x16, x8, x26\n\t"
        "umulh	x17, x8, x26\n\t"
        "mul	x19, x9, x26\n\t"
        "umulh	x20, x9, x26\n\t"
        "adds	x5, x5, x16\n\t"
        "adcs	x6, x6, x17\n\t"
        "adc	x13, xzr, xzr\n\t"
        "adds	x6, x6, x19\n\t"
        "adc	x13, x13, x20\n\t"
        /*   Add overflows at 2 * 64 */
        "mov	x26, #15\n\t"
        "bic	x7, x7, x26, lsl 60\n\t"
        "adds	x6, x6, x12\n\t"
        "adc	x7, x7, x13\n\t"
        /*   Subtract top at 2 * 64 */
        "subs	x6, x6, x8\n\t"
        "sbcs	x7, x7, x9\n\t"
        "sbc	x26, x26, x26\n\t"
        /*   Conditional sub order */
        "mov	x16, #0xd3ed\n\t"
        "movk	x16, #0x5cf5, lsl 16\n\t"
        "movk	x16, #0x631a, lsl 32\n\t"
        "movk	x16, #0x5812, lsl 48\n\t"
        "mov	x17, #0x9cd6\n\t"
        "movk	x17, #0xa2f7, lsl 16\n\t"
        "movk	x17, #0xf9de, lsl 32\n\t"
        "movk	x17, #0x14de, lsl 48\n\t"
        "and	x16, x16, x26\n\t"
        "and	x17, x17, x26\n\t"
        "adds	x4, x4, x16\n\t"
        "adcs	x5, x5, x17\n\t"
        "and	x26, x26, #0x1000000000000000\n\t"
        "adcs	x6, x6, xzr\n\t"
        "mov	x25, #15\n\t"
        "adc	x7, x7, x26\n\t"
        "bic	x7, x7, x25, lsl 60\n\t"
        /* Store result */
        "stp	x4, x5, [%x[s]]\n\t"
        "stp	x6, x7, [%x[s], #16]\n\t"
        : [s] "+r" (s)
        : [a] "r" (a), [b] "r" (b), [c] "r" (c)
        : "memory", "cc", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11",
            "x12", "x13", "x14", "x15", "x16", "x17", "x19", "x20", "x21",
            "x22", "x23", "x24", "x25", "x26"
    );
}

#endif /* HAVE_ED25519 */
#endif /* !CURVE25519_SMALL || !ED25519_SMALL */
#endif /* HAVE_CURVE25519 || HAVE_ED25519 */
#endif /* __aarch64__ */
#endif /* WOLFSSL_ARMASM */
#endif /* WOLFSSL_ARMASM_INLINE */
